网上有很多解释KMP算法的文章,A_B_C_ABC(见附件)的 这篇很详细,反复看了好几遍,总算理解了个大概,但是总觉得没那么爽快。其实,一种算法各人有各人的理解方法,找到适合自己理解的才容易记住。下面是我对 这个算法的一些理解:
int strstr(char *sub, char* str){
int i=0;
char *p=str, *q=sub;
while(*(p+i)!='\0'&&*(q+i)!='\0'){
if(*(q+i)==*(p+i))
i++;
else{
p++;
i=0;
}
}
if(*(q+i)=='\0')
return p-str;
return -1;
}
下面说说我理解的KMP算法,与普通匹配算法不一样的是,KMP算法在子串匹配失效的时候,下一步并不是重新从子串的头部开始匹配,而是根据一下 next函数计算出下一步应该从子串的什么部位开始匹配。举个例子更容易说明
void calnext(char* P, int next[]){
next[0] = -1; //第一个元素的next总是-1, 因为根据(1) , 我们并找不到一个k比j=0小
for(int i=1; i<strlen(P); i++){
int k = next[i-1]; //因为采用递归的方法, 为了计算next[i], 先记录下next[i-1] 而且假设next[i-1]已知
while(P[k+1]!=P[i]&&k>=0){ // 递归
k = next[k];
}
if(P[k+1]==P[i]) //如果相等而结束, 则找到一对长度为k的前缀字串和后缀字串
next[i] = k+1; //增加了一个相同项
else
next[i] = -1; //其他情况
}
}
匹配的代码:
int find(char*T, char* pat){
int n = strlen(pat);
int *next = new int[n];
calnet(pat, next);
char *p=T, *q=pat;
int i=0;
while(*p!='\0'&&(*(q+i)!='\0')){
if(*p==*(q+i)){
p++;
i++;
}else{
if(i==0)
p++;
else
i = next[i-1]+1;
}
}
if(*(q+i)=='\0')
return p-T-n;
else
return -1;
}