1.首先明确,next数组存在的意义是什么: 示例如下:
主串: a b a b c a b c a c b a b
模式串: a b c a c
匹配过程如下:
第一次匹配:
这个时候,如果不用KMP,而是用BF,那么我们的做法很明显:
尝试模式串的第一个字符和主串的第二个字符进行匹配。
很明显,这是多余的,这是肯定不成立的,而next数组直接告诉我们,跳过这一步,直接如下
这就是next的作用,如果还不明显,你再看上图,模式串的第五位是c和主串相对位置的b不匹配,那么按照BF算法,我们需要
再用主串的第四位和模式串的第一位比较,但是,很舒服,next数组告诉我们不用这样,直接如下
以上就是next的作用,跳过无用的匹配。
2.思考,next为什么可以这样做呢?
首先,什么是next数组:
上述模式串的next数组如下:
a b c a c
0 1 1 1 2
简而言之,每个字母x对应的next数组值是这样的出来的:x前的子串和主串的前几个字母相同,则只需要比较x和主串的第y个元素就好了,那么这个y就是next[x的索引]的值。
下面引入求next数组的算法:
next存储起始从1开始
void GetNext(string s,int next[])//s是模式串
{
int i=1,j=0;next[1]=0;
while(i
if(j==0||s[i]==s[j]){
i++;j++;
next[i]=j;
}
else{
j=next[j];//这一步很关键,他起到的作用就是刚才上面讲到的配对失败之后,直接跳到指定的位置
}
}
}
既然已经得到next数组了,那么实际操作就很简单了,附上KMP代码:
int KMP(string s,string t,int pos)//参数分别是主串,模式串,求模式串在主串第pos个字符之后的位置
{
int i=pos,j=1;
while(i
if(j==0||s.data[i]==t.data[j]){
i++;j++;//均后移一位
}
else j=next[j];//找到适当的位置
}
if(j>t.length())return i-t.length();//匹配成功
else return -1;
}