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;
}