字符串匹配算法KMP详解
RT,今日十分地无聊,刷了一波水题,在刷水题的过程中也发现了不少问题,下面顺便对KMP进行一个小讲解
原理
首先,KMP是一个字符串匹配算法,这个应该周所周知。它的思路大概是对模式串构造一个类似于状态机一样的东西,构造出它的失配函数以及失配边,然后在字符串匹配的时候进行快速转移的一个算法
构造失配函数时,有一个十分误导的说法,叫做自己匹配自己,这个虽然是有那么点感觉,但其实对学习毫无帮助,只是用来应付萌新的问题的东西。。。
其实就是通过观察性质进行递推的过程,鉴于网上相关资料已经很多,具体过程可参考代码
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn1 1000005
#define maxn2 10005
using namespace std;
char txt[maxn1],tem[maxn2];
int len1,len2,ans=0;
int f[maxn2];
void init(){
len1=strlen(txt);
len2=strlen(tem);
f[0]=f[1]=0;
for(int i=2;i<=len2;i++){
int k=f[i-1];
while(k!=0&&tem[k]!=tem[i-1]) k=f[k];
f[i]=(tem[k]==tem[i-1])?k+1:0;//注意这个地方很重要
}
return;
}
void KMP(){
int pos=0;
for(int i=0;i<len1;i++){
while(pos!=0&&txt[i]!=tem[pos]){
pos=f[pos];
}
if(txt[i]==tem[pos])
pos++;
if(pos==len2){
pos=f[pos];
ans++;
}//为了方便,特意构造了一个f[len2]
}
}
int main(){
/*freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);*/
int T;
scanf("%d",&T);
while(T--){
scanf("%s\n%s",tem,txt);
init();
KMP();
printf("%d\n",ans);
ans=0;
}
return 0;
}
细节
主要有如下:
1.正如上方“注意这个地方很重要”所言,那里的
2.为了匹配时的方便,我们可以计算一个额外的
应用
它的应用中最常见的就是 就算了有时间可能会予以补充
例题
基本都是一些水题,下面会链上题解