回忆KMP算法
很多人都说KMP很难理解。表示很赞同,有这样一句话,模仿的,终归不是自己的。
今天基本上休息的时间都花在KMP上了,终于写完了它的next算法(算回忆吧,以前也写过),好好总结一下,作为一个算法菜鸟,复习是必修课。
我的思路:
首先是一个思维的转换,当主串和模式串发生匹配时:
S[1] S[2].....S[ i ] S[i+1].........S[i+j-1] S[i+j].........
P[1] P[2]..............P[j-1] P[j] (1)
此时如果P[j]失配 很显然KMP的思路是去寻找这样一个模式串的子串去匹配(1)
P[1] P[2].............P[j-k+1]......... P[j-1] P[j] P[j+1]
p[1]...............p[k-1] p[k] p[k+1]
反证一下为什么KMP要这样一个条件 不可能存在k' >k 满足上述关系
我们说当P[j]失配时,在模式串滑动的过程中肯定要让P[j-1]得配,而这个k值必须是最大的,这一点其实是不言而喻的。(理解是王道,多揣摩。。)
这样一来,问题就转化为怎么找到这个恰到好处的 p[k-1]
先假设 k找到了,并且给它一个身份,放在next[j]中 即next[j]=k
我们的下一步是求next[j+1]
1' 如果p[j]=p[k] (都是同一个串 没必要分大小写了)
那么 next[j+1]=k+1 ,显然的嘛,因为对于j+1来说我寻找的next[j+1]的p[k-1]已经找到了啊。。。
2' 反之 相当于p[k]对于p[j]失配了 显然我们要这样做,像当p[j]失配时一样 ,重复我们的思路
p[1]...............p[k-1] p[k] p[k+1]
p[1].......p[k'-1] p[k']
k'=next[k]
如果匹配成功
next[j+1]=k'+1
否则
直到 next[1]=0
下面我用C++语言以递推的方式描述上述过程
void getNext(int *next,char *str,int len)
{
next[0]=-1;
int i;
int j=-1;
for(i=1;i<len;)
{
if(j==-1)
{
next[i]=j+1;
j=next[i];
i++;
}
if(j!=-1&&s[i]==s[j])
{
next[i]=j+1;
j=next[i];
i++;
}
else
{
j=next[j];
}
}
}