Kmp算法的两种写法

来源:互联网 发布:win10没有网络协议 编辑:程序博客网 时间:2024/06/05 05:04

总结:KMP算法的重点是求next数组。注意,该数组只和模式串有关系,和要匹配的串没有关系。


两种写法的基本思想是一致的。只是求next数组的方式不同,next数组所得的值也有所不同,代表的含义也不同。


原理不多说,网上讲的很多,这里只贴出完整的实现代码。

一般网上讲解的求next数组的都是针对方法二的。


第一种优化写法。

next[i]表示匹配串在i处如果匹配失败下次移到的位置. 

const int N = 100;int next[N];int pattern_len, str_len;char pattern[N];char str[N];//求next数组的值. 即预处理void getNext1(){int i = 0, j = -1;next[0] = -1;while (i < pattern_len - 1){//cout << i << " " << j << endl;if (j == -1 || pattern[i] == pattern[j]){++i;++j;if (pattern[i] != pattern[j])next[i] = j;elsenext[i] = next[j];}elsej = next[j];}}int kmp1(){int i = 0, j = 0;str_len = strlen(str);while (i < str_len && j < pattern_len){if (j == -1 || str[i] == pattern[j]){++i;++j;}elsej = next[j];}if (j >= pattern_len)return i - pattern_len;elsereturn -1;}


第二种,经典写法. 

next[i]表示  最远匹配到的位置。

以ABCDABD为例:-1 -1 -1 -1 0 1 -1 

abcbabc : -1 -1 -1 -1 0 1 2 

void getNext2(){next[0] = -1;int pre; //注,此处的i是从1开始的for (int i = 1; i < pattern_len; ++i){pre = next[i - 1];//向前回溯 prewhile (pre >= 0 && pattern[pre + 1] != pattern[i]){pre = next[pre];// cout << i << "  index: " << pre << "  back " << endl ;}// cout << "i:" <<i << "   " << pre << endl;if (pattern[pre + 1] == pattern[i])next[i] = pre + 1;elsenext[i] = -1; //由于前面已经回溯,这里可直接赋值为-1}}int kmp2(){int p_index = 0, t_index = 0;while (p_index < pattern_len && t_index < str_len){if (str[t_index] == pattern[p_index]){++t_index;++p_index;}else if (p_index == 0)++t_index;elsep_index = next[p_index - 1] + 1;}if (p_index == pattern_len)return t_index - pattern_len;elsereturn -1;}


int main(){freopen("in.txt", "r", stdin);while(gets(str)){gets(pattern);pattern_len = strlen(pattern);//if(str[0] == '#') continue;getNext1();int ans = kmp1();cout << "next1: ";for(int i=0; i<pattern_len; i++) cout << next[i] << " ";cout << endl;cout << ans << endl;getNext2();cout << "next2: ";for(int i=0; i<pattern_len; i++) cout << next[i] << " ";cout << endl; ans = kmp2();cout << ans << endl;}}


测试数据:

/*
abadfabaabacd
abac
ababcbabcbaca
abcbabc
 */


打印结果:

next1: -1 0 -1 1 8next2: -1 -1 0 -1 8next1: -1 0 0 0 -1 0 0 2next2: -1 -1 -1 -1 0 1 2 2


原创粉丝点击