KMP算法
i指针表示主串(被匹配串),j指针表示模式串
首要确认next[]的值,决定匹配串要移动的距离
举例说明:匹配串为S{abcac},主串(被匹配串)为P小标从0开始,(=?表示是否相等)
next[0]=-1
next[1]=0
next[2],则看s[0]=?s[1],若相等,则next[2]=1,即看字符串S[2]前面是否有字串相等,字串{a}!={b},那么next[2]=0
next[3],则看s[0]=?s[2],s[0,1]=?s[1,2],即看字符串S[3]前面是否有字串相等,next[3]的值为最大相等字串的长度,
这里字串{a}!={b},{ab}!={bc},则next[3]=0
next[4],则看s[0]=?s[3],s[0,1]=?s[2,3],s[0,1,2]=?s[1,2,3]是否有字串相等,next[4]取最大的字串长度,这里next[4]=1.
KMP的优点在于被匹配的串指针不需要回溯,只需匹配串移动即可,没下一次匹配,将S[next[i]]的位置与被匹配串指针对应。
若被匹配串为abcabacabcac,匹配过程为(i指针表示被匹配串,j指针表示匹配串):
abcac
(下标从0开始),i=4,j=4时不匹配,next[4]=1,那下一次匹配s[1]即{b}将与i=4即{b}对应,即
abcabacabcac
abcac
i=5,j=2时不匹配,next[2]=0,那么下一次匹配s[0]即{a}与i=5即{a}匹配,即
abcabacabcac
abcac
i=6,j=1时,不匹配,next[1]=0,那么下一次匹配s[0]即{a}与i=6即{c}匹配,即
abcabacabcac
abcac
i=6,j=0时,不匹配,next[0]=-1.那么下一次匹配
abcabacabcac
abcac 匹配成功
但是算法可以改进,改进之后即:
比较S[j]和S[k],若不等,则 nextval[j]=next[j];若相等nextval[j]=nextval[k];(*)
举例:(下标从0开始)
012345678
p: aaabaaaab
s: aaaab
i=3,j=3时,不匹配,next[3]=2,常规KMP下一次匹配为P[3]对应S[2],但是s[2]=s[3],所以无需进行常规KMP的下一次匹配,跳到下下次的常规KMP
匹配,即P[3]与s[1]对应匹配,但是s[1]=s[3],也无需进行,继续跳到下一次,实际上,因为模式中的第1、2、3个字符和第4个字符都相等,因此,
不需要再和主串中第4个字符相比较,而可以将模式一次向右滑动4个字符的位置直接进行i=4,j=0时的字符比较。
代码实现如下(unix环境):
有疑问的人可以去看看李春葆的PPT,讲得还是很清楚的。