最近在看严蔚敏版的数据结构,看到kmp的时候 折腾了好半天 发现这个版本的跟网上一些博客里的写法不一样,所以写此博客记录一下自己理解的版本。
假设有字符串s和p,循环比较s[i]和p[j]是否相等,如果相等,i++,j++,继续比较,如果不相等,kmp则采取的就是i不动,移动j的位置,充分利用p字符串中重复字符集的作用。将j移动到next[j]的位置,将s[i]和p[next[j]]比较,看是否相等,此时有两种情况:
- 1.相等,则执行i++,j++,继续往后判断;
- 2.不相等。此时,将j移动到next[next[j]]的位置,继续判断,此时若s[i]==p[next[next[j]]],则到步骤一,否则步骤二,继续往后移动,直到j移到p字符串的开头,说明没有匹配到,此时i++,j++继续往后判断
然后重点就是next数组的求法:
求next数组时候,将匹配字符串p既当做主字符串,又当做模式字符串。过程类似以上循环的步骤。假如一直循环,当s[i]与p[next[m]]相等时,next[j+1] = next[m]+1;
如果一直到开头都匹配不到时,则next[j+1] = 1;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int *getNext(char *s,int next[],int len);
//获取next数组
int *getNext(char *s,int next[],int len){
int k=0,j;
next[0] = -1;
next[1] = 0; //由定义 next[0]=1
for(j= 2;j<len+1;j++){
k = next[j-1];
while(k>0 && s[j-2] != s[k-1]){
k = next[k];
}
if(s[j-2] == s[k-1]){
next[j] = k+1;
}else
next[j] = 1;
}
return next;
}
int main(){
// char string[]="asdabaadcdabbaabc";
// char mat[] = "adcd";
// char *s = string;
// char *m = mat;
char *string= (char *)malloc(sizeof(char));
char *mat = (char *)malloc(sizeof(char));
int i=0,j=1,q,k;
int len_mat;
int len_str;
int count = 0;
int *next;
scanf("%s",string);
scanf("%s",mat);
len_mat = strlen(mat);
len_str = strlen(string);
next = (int *)malloc((len_mat+1)*sizeof(int));
next = getNext(mat,next,len_mat);
for(i = 0;i<len_str;i++){
if(string[i] != mat[j-1])
count = 0;
while(string[i] != mat[j-1] && j>0)
{
j = next[j];
}
if(string[i] == mat[j-1])
{
count++;
j++;
}
if(j == 0){
j = 1;
}
if(count == len_mat){
printf("%d\n",i-len_mat+2);
count = 0;
j = 1;
i--;
}
}
if(count == len_mat){
printf("match: %d %d\n",i-len_mat+1,i);
}else{
printf("not match!\n");
}
for(i = 1;i<len_mat+1;i++)
printf("%d ",next[i]);
}