KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
中文名 KMP算法
外文名 The Knuth-Morris-Pratt Algorithm
输入 正文串T[1,n]和模式串W[1,m]
输出 匹配结果match[1,n]
发现者 D.E.Knuth等
时间复杂度 O(m+n)
先对t串进行预处理 算出next数组
在与s串进行kmp
在写的时候记得将next写成Next 不然交上去CE 下面程序就不改了
下面的代码也是[poj 3461]的答案
#include<stdio.h>
#include<string.h>
#include<iostream>
#define N 1000010
using namespace std;
int next[N],ans,ls,lt;
char s[N],t[N];
int n;
void makenext()
{
next[1]=0; int k=0,j=1;
while(j<=lt){
if(k==0||t[j]==t[k]){
j++;k++;
next[j]=k;
}
else k=next[k];
}
}
void fnd()
{
int i=1,j=1;
while(i<=ls)
{
if(s[i]==t[j]||j==0){i++;j++;}
else j=next[j];
if(j>lt) {j=next[j];ans++;}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
ans=0;
memset(s,0,sizeof(s)); memset(t,0,sizeof(t));
s[0]='0';t[0]='0';
scanf("%s",t+1);
scanf("%s",s+1);
ls=strlen(s)-1,lt=strlen(t)-1;
makenext();
fnd();
cout<<ans<<endl;
}
return 0;
}
改进版 对于aaaab这种情况
如第4个不匹配直接跳回第一个a
不用找第3个第2个a浪费时间
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define N 1000
using namespace std;
int next[N],ans,ls,lt;
char s[N],t[N];
int n;
void makenext(){
next[1]=0;
int k=0,j=1;
while(j<=lt){
if(k==0||t[j]==t[k]){
j++;k++;
if(t[k]==t[j]) next[j]=next[k];//aaaab 这种情况
else
next[j]=k;
}
else k=next[k];
}
}
void fnd(){
int i=1,j=1;
while(i<=ls){
if(j==0||s[i]==t[j]){
i++;j++;
}
else j=next[j];
if(j>lt) {j=next[j];ans++;}
}
}
int main(){
gets(s+1);
gets(t+1);
ls=strlen(s+1);
lt=strlen(t+1);
return 0;
}