您的位置:首页 > 其它

字符串匹配--(K)MP模板

2015-05-17 15:36 274 查看
大白书型模板,并没有写成函数形式:

这个是下标从0开始的:

此外,对于一个长度为 m 的串自匹配,在此模板中 m-p[m] 就是这个串的最小循环节长度(最后一个循环可以不完整)

另一个关于自匹配后的失配指针的性质:对于该串的所有可以作为循环节的长度是:m-p[m] , m-p[p[m]] , m-p[p[p[m]]]……直到 p[x] = 0。

#include<stdio.h>
#include<string.h>

const int maxn=1e6+5;
const int maxm=1e4+5;

char s[maxn],t[maxm];    //s为待匹配串,t为模板串
int p[maxm];    //自匹配数组

int main(){
while(scanf("%s%s",s,t)!=EOF){    //这个是字符串从下标0开始的
int i,j,ans=0;    //ans记录字符串出现次数
int n=strlen(s),m=strlen(t);    //在题目中遇到过,其实strlen很慢,所以如果不先存起来可能有TLE的风险
p[0]=p[1]=0;    //初始化自匹配数组
for(i=1;i<m;i++){    //自匹配
j=p[i];
while(j&&t[i]!=t[j])j=p[j];
p[i+1]=t[i]==t[j]?j+1:0;
}
j=0;            //注意 j=0
for(i=0;i<n;i++){    //串匹配
while(j&&s[i]!=t[j])j=p[j];
if(s[i]==t[j])j++;
if(j==m){
ans++;        //此处记录出现次数(模板串在待匹配串中可重叠),或改为直接break表示是否出现过
}
}
printf("%d\n",ans);
}
return 0;
}


数组下标从1开始:

#include<stdio.h>
#include<string.h>

const int maxn=1e6+5;
const int maxm=1e4+5;

char s[maxn],t[maxm];
int p[maxm];

int main(){
while(scanf("%s%s",s+1,t+1)!=EOF){   // 。。这个是从下标1开始的,恩修改的还是比较多的所以不是很建议
int i,j,ans=0;
int n=strlen(s+1),m=strlen(t+1);
p[1]=p[2]=1;
for(i=2;i<=m;i++){
j=p[i];
while(j>1&&t[i]!=t[j])j=p[j];
p[i+1]=t[i]==t[j]?j+1:1;
}
j=1;
for(i=1;i<=n;i++){
while(j>1&&s[i]!=t[j])j=p[j];
if(s[i]==t[j])j++;
if(j==m+1){
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: