更简单的KMP前缀表构建。这个实现会出什么问题?

时间:2018-05-08 23:08:21

标签: algorithm knuth-morris-pratt

KMP算法需要一个前缀表,然后在失败后知道它可以安全跳过多少个字符。前缀表的一般概念是,它将告诉您给定模式P,在给定位置i和char C,共有多少个字符后缀到C的前缀为P

int[] T = new int[P.length()];
int i = 0;
for (int j = 1; j < P.length(); ++j) {
  if (P.charAt(j) == P.charAt(i)) {
    i++;
  } else {
    i = 0;
  }
  T[j] = i;
}

这就是我想出的。我环顾四周,实现似乎总是截然不同。我尝试过几个例子(例如ABABACA),但是我的实现和例如KMP prefix table似乎产生了相同的结果。

有谁能告诉我我的实现中的逻辑错误是什么,以及在为KMP算法生成正确的前缀表时失败的输入是什么类型?

由于

1 个答案:

答案 0 :(得分:1)

您的算法的一个特征是表中的每个条目都比前一个条目多0或1。因此,挑战在于找到一个字符串,其中表中的条目小于前一个条目,但不是0。

其中一个字符串是&#34; ABACABABC&#34; (来自this wikipedia article)。

前缀表是

{0,0,1,0,1,2,3,2,0}  from the linked answer
{0,0,1,0,1,2,3,0,0}  your proposed code
               ^------different here

感兴趣的条目是3,然后是2.

考虑7个字符匹配时会发生什么。输入字符串看起来像

ABACABA?    

在哪里?是不匹配的角色,所以?不是B. ABA?可以匹配ABAC,因此前缀长度为3。

现在考虑当8个字符匹配时会发生什么:

ABACABAB?

在哪里?不是C.在这种情况下,AB?可以匹配ABA,因此前缀长度为2。

这表明前缀表可以的条目小于上一个条目,但不是0。