朴素匹配模式虽然简单易懂,但十分耗费时间。KMP算法思路如下:
首先我们要了解最大前后缀相等的概念。(读者自行查阅)
代码如下,xdm自己理解吧。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
void Getnext(char* k,int* next);
int KMP(char* s,char* k);
int main(){
char s[100],k[100];
scanf("%s",s);
scanf("%s",k);
int a=KMP(s,k);
printf("从第%d个开始匹配",a+1);
}
int KMP(char* s,char* k){
int a=strlen(s);//母串长度
int b=strlen(k);//子串长度
int m=0;
int n=0;//m为母串长度,n为子串长度
int *next=(int*)malloc(sizeof(int)*m);//next数组
Getnext(k,next);//next数组赋值
while(m<a&&n<b){
if(s[m]==k[n]){//匹配成功的情况
m++;
n++;
}
else{//碰到不匹配的情况
if(m>0){
n=next[n-1]+1;//KMP算法精髓,求字符串最长相等前后缀
}
else{//m==0的情况
m++;//第一个就匹配不成功的情况 ,直接让母串往后挪
}
}
}
if(n==b){
return m-b;//返回母串匹配成功的位置
}
return -1;//匹配不成功
}
void Getnext(char* k,int* next){//一个匹配为0
next[0]=-1;//-1表示没有匹配
int length=strlen(k);
for(int i=1;i<length;i++){
int j=next[i-1];
if(k[j+1]==k[i])
{
next[i]=j+1;//在next[i-1]的基础上进行判断
}
while((j>=0)&&k[j+1]!=k[i])
{
j=next[j];//??唯一难点 ,当k[j+1]与k[i]不匹配时, 我们将从0到j的这一段的next拿出来。
}
if(k[j+1]==k[i])
{
next[i]=j+1;
}
else{
next[i]=-1;
}
}
for(int i=0;i<length;i++){
printf("%d ",next[i]);
}
}