(1) n[0] = -1,对于i > 0的n[i] ,假定已知前一位置的特征数 n[i-1]= k ;
(2) 如果pi = pk ,则n[i] = k+1 ;
(3) 当pi ≠ pk 且k≠0时,则令k = n [k -1] ; 让(3)循环直到条件不满足;
(4) 当qi ≠ qk 且k = 0时,则ni = 0;
根据以上分析,可以得到Next特征数组的计算方法,算法代码如下:
1.void get_next(SString T, int &next[])
2.{
3. //求模式串T的next函数值并存入数组next
4. i = 1; next[1] = 0; j = 0;
5. while (i < T[0])
6. {
7. if(j ==0 || T[i] == T[j])
8. {
9. ++i; ++j; next[i] = j;
10. }
11. else
12. {
13. j = next[j];
14. }
15. }
16.}
文献[5]中解释了以上计算方法存在一定缺陷,存在多比较的情况,可对其进行修正,得到如下算法:
1.void get_next(SString T, int &next[])
2.{
3. //求模式串T的next函数值并存入数组next
4. i = 1; next[1] = 0; j = 0;
5. while (i < T[0])
6. {
7. if(j ==0 || T[i] == T[j])
8. {
9. ++i; ++j;
10. if (T[i] != T[j])
11. next[i] = j;
12. else
13. next[i] = next[j];
14. }
15. else
16. {
17. j = next[j];
18. }
19. }
20.}
4、算法实现
KMP算法的难点就是有限自动机的构造和特征向量的计算。解决了这两个问题后,具体匹配算法就很简单了。
int Index_KMP(SString S,SString T,int pos){
//利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法。
//其中,T非空,1≤pos≤StrLength(S)。
i=pos; j=1;
while(i <= S[0] && j<= T[0]){
if(j == 0 || S[i] == T[j]) { ++i; ++j; }//继续比较后继字符
else j = next[j];//模式串象右移动
}
if(j>T[0]) return i-T[0];//匹配成功
else return 0;
}//Index_KMP
算法相关理论分析与证明,以及算法复杂性分析,若感兴趣请参考文献[3]、[4]、[5],这里不再赘述。
5、参考文献
[1] http://wansishuang.javaeye.com/blog/402018
[2] http://richardxx.yo2.cn/articles/kmp和extend-kmp算法.html
[3] KMP算法讲义PPT(Hu Junfeng, Peking University)
[4] 算法导论(第32章 字符串匹配)
[5] 数据结构(第4章 串)