KMP是经典的字符串匹配算法,时间复杂度为o(m+n)
KMP原理
(待补充)
前一阵子自己试着写了一下,代码如下:
/* *KMP算法实现 *包含两部分:1.模式串前缀函数的计算(预处理) * 2.文本与模式串的匹配 * *模式串前缀函数的计算(预处理): *假设模式串的长度为len,通过计算模式串从1到len为止的所有子串的 *最大前缀长度,来填充前缀数组。这个前缀满足这种特性:是这个子串的 *真后缀,而且是这个子串的真前缀(即不为子串本身),能满足以上两者 *的最大的那个串,取其长度。例如:abcabc,其中abc既是这个子串的后缀, *也是这个子串的前缀,并且是最长的,所以其前缀函数值为3. * *计算所有子串的前缀函数值: *从第一个字符开始计算,因为第一个字符没有真前缀,所以取0 *接下来,对每个子串,进行判断,如果失配,则回溯到之前更短的前缀值 *看是否有一个与之可以匹配的。如果匹配,则直接在原有值+1,并移动指针 *例如:abkabcabkabk,当运行到k时,这时前缀指针在c,c!=k,因此失配,通过 *循环返回到abkab的最长前缀值,即2,此时前缀指针指向k,k==k,因此匹配, *跳出循环,在目前的基础上+1,即为3.前缀指针继续向前移动到a */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> void compute_prefix(char pattern[100],int prefix[100]){ int len=strlen(pattern),i,prelen; prefix[0]=0; prelen=0; for(i=1;i<len;i++){ while(prelen>0&&pattern[prelen]!=pattern[i]) prelen=prefix[prelen-1]; if(pattern[prelen]==pattern[i]) prelen++; prefix[i]=prelen; } }; int main(){ char text[1000],pattern[100]; int prefix[100],i,q=0; while(scanf("%s%s",text,pattern)!=EOF){ compute_prefix(pattern,prefix); for(i=0;i<strlen(text);i++){ while(q>0&&pattern[q]!=text[i]) q=prefix[q-1]; if(pattern[q]==text[i]) q=q+1; if(q==strlen(pattern)){ printf("pattern occurs:%d",i+1-strlen(pattern)); q=prefix[q-1]; } } } return 0; }