KMP算法看了好几遍才慢慢搞懂,至于算法导论上用来解决相同问题的RF算法和有限状态机算法则更是云里雾里,暂且不管吧。
KMP的算法重点在于如何计算next[ ]数组的值
假设text为原字符串(t),长度为n。pattern为需要查询的字符串(p),长度为m
假设 next[i] =k ,则说明在p的第i个字符和之前,有k个字符与p最开始的k个字符重复。
比如 p = "ababacab"
可得
next [ 0 ] = 0;
next [ 1 ] = 0;
next [ 2 ] = 1;
next [ 3 ] = 2;
next [ 4 ] = 3;
next [ 5 ] = 0;
next [ 6 ] = 1;
next [ 7 ] = 2;
比较第 next[ i-1] 个数和 第 i 个数,如果相等则
next[ i ] = next [ i -1 ] + 1;
通过递推方式,可在O(m)次内计算出next数组
计算出next数组后,当比较p 中第 i 个字符,和 t 中第 s 个字符时,若不相等
查看 next[ i-1 ],若>0 则重置 i = p + next[ i-1 ],s保持不变
若 i = p 则将s = s + 1;
只需循环遍历 t 一次,即可找到匹配字符串 复杂度为 O (n)
给出代码实现,自己写的,可能不规范,仅作以后参考
int *get_next(char *p){
int len = strlen(p);
int *next = new int[len];
next[0]=0;
for(int i=1;i<len;i++){
if((0+next[i-1] != i)&&p[0+next[i-1]] == p[i]){
next[i] = next[i-1] + 1;
}else if(p[0] == p[i]){
next[i] = 1;
}else{
next[i] = 0;
}
}
return next;
}
void find(char *t, char *p, int next[]){
if(t==NULL || p == NULL) return;
char *i=p;
while(*t!='\0'){
while(*i!='\0' && *t!='\0' && *i==*t){
i++;
t++;
}
if(*i=='\0'){
cout<<(t-(i-p))<<endl; //输出匹配结果
i = p;
}else if(i==p){
t++;
}else{
i = p + next[i-p-1];
}
}
}