KMP算法,为什么next数组j==1时,k值为0
本文核心
next[1] = 0 是为了代码能正常运行所进行的设计。不要用kmp算法的思想去理解它,而要从如何真正实现kmp算法的角度来思考。
前提
本帖仅说明为什么next[1] 的值要设定为0,具体kmp算法有许多厉害的大佬进行解析,这里不做赘述。这里假设看到这个帖子的各位已经基本了解过kmp算法了。
该问题基于以下kmp算法的代码进行讨论,网上有很多种实现代码,请注意区分。
代码如下:
以下是求next数组的代码。
void getnext(Str substr, int next[]){
int i = 1, j = 0;//字符串冲下标1开始储存字符,故i初始为1
next[1] = 0;
while(i<substr.length){
if(j==0||substr.ch[i]==substr.ch[j]){
++i;
++j;
next[i] = j;
}
else{
j = next[j];
}
}
}
以下是kmp算法的代码:
int kmp(Str str, Str substr, int next[]){
int i = 1,j = 1;
while(i<=str.length && j<=substr.length){
if(j==0 || str.ch[i] == substr[j]){
++i;
++j;
}
else{
j = next[j];
}
}
if(j > substr.length){
return i-substr.length;
}
else{
return 0;
}
}
正文
我们知道next[j] 中的值代表在j位置匹配出错时应该跳转到的模式串中的字符的位置。我在看kmp算法的时候就想,当 j == 1 时,发生匹配错误,不应该直接跳转到模式串的第一个位置么?此时next[j] 不应该等于1么?
next[1]=0是为了代码的实现进行的设计,不符合kmp算法的思想
在本帖给出的代码中,next[1] = 0 的意义是为了实现:j=1处字符发生不匹配时,将第一个字符与下一个字符进行匹配。这个功能由kmp算法中的
if(j==0 || str.ch[i] == substr[j]){
++i;
++j;
}
进行实现。
在判断语句中,j==0 会触发 i 与 j 同时加一,此时 i 指向主字符串中下一个需要对比的字符,j == 1, 指向模式串中的第一个字符。
所以不用纠结为什么next[1]=0与kmp的理论不符,这只是为了真正的代码的能运作起来而进行的设计而已。