KMP字符串匹配算法
KMP算法的要点是避免回溯和Next[]数组,其中,Next[]数组中存的是最长公共前后缀的长度.
1.KMP模板
例题:HDU2087剪花布条
int Next[N],cnt;
//构建Next[]数组 void getNext(char *p,int plen){ Next[1]=Next[0]=0; for(int i=1;i<plen;i++){ int j=Next[i]; while(j&p[i]!=p[j])j=Next[i]; if(p[i]==p[j])Next[i+1]=j+1; else Next[i+1]=0; } }
//KMP算法 void kmp(char *s,char *p){ int last=-1,slen=strlen(s),plen=strlen(p); getNext(p,plen); int j=0; for(int i=0;i<slen;i++){ while(j&&s[i]!=p[j])j=Next[j]; if(s[i]==p[j])j++; if(j==plen){ if(i-last>=plen){ cnt++; last=i; } } } }
2.DP+KMP
例题:HDU3336
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9,MOD = 1e4+7;
int dp[N],nex[N];
char s[N];
int len1,len2;
void getnext(){
int i=0,j=-1;
nex[i]=j;
while(i<len1){
if(j==-1||s[i]==s[j])nex[++i]=++j;
else j=nex[j];
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int sum=0;
scanf("%d",&len1);
scanf("%s",&s);
memset(dp,0,sizeof(dp));
getnext();
for(int i=1;i<=len1;i++){
dp[i]=dp[nex[i]]+1;
sum=(sum+dp[i])%MOD;
}
printf("%d\n",sum);
}
return 0;
}
3.矩阵快速幂+KMP
例题:洛谷P3193
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
const int N = 5e3+255;
int f[N][30],n,m,k,nxt[N],match[N][50];
char md[N];
void kmp(){
nxt[0]=-1;
for(int i=1;i<=m;i++){
int j=nxt[i-1];
while(j!=-1&&md[j+1]!=md[i])j=nxt[j];
nxt[i]=++j;
}
nxt[0]=0;
for(int i=0;i<m;i++){
for(int j='0';j<='9';j++){
int t=i;
while(md[t+1]!=j&&t>0)t=nxt[t];
if(md[t+1]==j)t++;
if(t<m)match[i][t]++;
}
}
}
class matrix{
public:
int mr[25][25];
matrix(){
memset(mr,0,sizeof(mr));
}
matrix operator *(matrix b){
matrix ans;
memset(ans.mr,0,sizeof(ans.mr));
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
for(int p=0;p<m;p++){
ans.mr[i][j]+=mr[i][p]*b.mr[p][j];
ans.mr[i][j]%=k;
}
}
}
return ans;
}
}F,G;
matrix quickPow(matrix A,int pows){
matrix ans;
for(int i=0;i<=m;i++)ans.mr[i][i]=1;
while(pows){
if(pows&1)ans=ans*A;
pows>>=1;
A=A*A;
}
return ans;
}
int main(){
cin>>n>>m>>k;
scanf("%s",md+1);
kmp();
F.mr[0][0]=1;
for(int i=0;i<=m;i++){
for(int j=0;j<=m;j++){
G.mr[i][j]=match[i][j];
}
}
G=quickPow(G,n);
F=F*G;
long long ans=0;
for(int i=0;i<m;i++){
ans+=F.mr[0][i];
ans%=k;
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号