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; }
标签:int,void,Next,char,算法,KMP,字符串,plen From: https://www.cnblogs.com/zhanghx-blogs/p/17255646.html