文章图片来自:
如何更好地理解和掌握 KMP 算法?
下面总结了一下:
首先上代码:
char s[10001];//待匹配
char p[101];//匹配
int nxt[1001];
int ls,lp;//分别代表s,p的长度,在主函数里求一次,最好别在kmp里求,容易超时
void get_next()//求next数组的代码,我一般喜欢把数组定义成全局变量,然后就不用在括号写东西了
{
int i=0,j=-1;
nxt[0]=-1;
while(i<lp)//最好别写strlen(p),因为每次用都会算的话容易超时
{
if(j==-1||p[i]==p[j])
nxt[++i]=++j;
else
j=nxt[j];//看清楚,这一步i没有变
}
}
int kmp()//kmp算法,其实跟求nxt差不多
{
int i=0,j=0;
get_next();
while(i<ls&&j<lp)
{
if(j==-1||s[i]==p[j])
i++,j++;
else j=nxt[j];//这一步i没有变,回溯
}
if(j==lp)//说明找到了
return i-j+1;//返回下标
else
return -1;
}
以abababca求next数组为例:(lp=8)
从下标为1的元素开始,如图,现在模拟执行get_next()函数,i=1;j=-1;nxt[0]=-1;
i<lp,进入循环,由于此时,j=-1;执行if语句:nxt[1]=0;i=1;j=0;第一次循环执行完毕;此时i=1;j=0,如图a所示;
i= =2<lp,进入循环,此时,j= =0!=-1且p[i]!=p[j];执行else,j=nxt[1]=0;循环结束;
i= =2<lp,进入循环,此时,j= =0!=-1但是p[i]==p[j] (如图b),执行if语句,nxt[3]=1;j=1;i=3;循环结束;

i= =3<lp,进入循环,此时,j= =1!=-1但是p[i]==p[j],如图c,执行if语句,nxt[4]=2;i=4,j=2;循环结束;
i= =4<lp,进入循环,此时,j= =2!=-1但是p[i]==p[j],执行if语句,nxt[5]=3;i=5,j=3;循环结束;
i= =5<lp,进入循环,此时,j= =3!=-1但是p[i]==p[j],执行if语句(如图d),nxt[6]=4;i=6,j=4;循环结束;
重点来了,带你了解回溯:
i= =6<lp,进入循环,此时,j= =4!=-1且p[i]!=p[j],执行else语句,j=nxt[4]=2,循环结束;
i= =6<lp,进入循环,此时,j= =2!=-1且p[i]!=p[j],执行else语句,j=nxt[2]=0,循环结束;
i= =6<lp,进入循环,此时,j= =0!=-1且p[i]!=p[j],执行else语句,j=nxt[0]=-1,循环结束;
i= =6<lp,进入循环,此时,j= =-1;执行if语句(如图e):nxt[7]=0;i=7,j=0;循环结束;

i= =7<lp,进入循环,此时,j==0;但是p[i]==p[j],执行if语句:nxt[8]=1;i=8,j=1;循环结束,get_nxet()函数执行完毕
最后就形成了这个表:

添加链接描述
本文详细介绍了KMP算法的工作原理及实现过程,并通过实例演示了next数组的构造方法及其在字符串匹配中的应用。



43万+





