【问题标题】:Prefix table for KMP algorithmKMP 算法的前缀表
【发布时间】:2016-08-16 18:33:12
【问题描述】:

我正在通过 KMP 算法。尽管这个算法很容易理解,但我在这里有一个疑问。

前缀表算法:

void prefixTable(char p[], int m){
     int i=1, j=0, F[0] = 0;
     while(i<m){
        if(p[i]==p[j]){
            F[i]=j+1;
            i++;
            j++;
        }else if(j>0){
            j=F[j-1];
        }else{
            F[i]=0;
            i++;
        }
     }
}

如上图步骤 5 所示,i=5, j=3, j=F[j-1] 被执行为 j>0 。

我们为什么要取 F[j-1]?为什么我们不能直接使用 F[0]? 它如何保证算法的正确性?

【问题讨论】:

标签: algorithm string-matching


【解决方案1】:

j 是模式中的位置。

如果模式被处理到某个位置 > 0,那么如果模式包含自身的前缀,我们就不能将模式移动到第一个 (0) 位置。

应用于您的示例:模式为ababaca。尝试在abababaca的文字中找到它:

  • 算法将处理文本直到ababa|baca,其中模式为ababa|c
  • 将 j 设置为 F[0] = 0,意味着将模式设置为 |ababac,它永远不会匹配 baca(注意 i 不会被更改)
  • 将 j 设置为 F[4] = 3,意味着将模式设置为 aba|bac,这将匹配 baca
  • 匹配后,模式处于ababac| 状态,文本处于abababac|a 状态,很明显找到的模式是ab[ababac]a

【讨论】:

  • 正如您在第 3 点中所解释的,为什么我们在构建前缀函数时要使用 F[j-1]?它如何确保获得正确的比较位置?
  • KMP 算法设计为永不追溯。这意味着一旦到达文本中的某个位置,指针将永远不会移动到该位置之前。因此,必须调整模式中的位置以匹配文本位置。计算 F[i] 使其始终包含要与文本位置对齐的右移。
猜你喜欢
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多