#include <bits/stdc++.h> using namespace std; #define mod 10007 const int maxn=2e5+7; int f[maxn]; char s[maxn]; void getfail(char *T) { int i=1,j=0,n=strlen(T+1);f[1]=0; while(i<n){ if(j==0||T[i]==T[j])//确定当前位,给下一位一个机会 ++i,++j,f[i]=j; else j=f[j]; } } int main() { int T,n; cin>>T; while(T--) { scanf("%d%s",&n,s+1); getfail(s); int cnt=0; for(int i=1;i<=n;i++){ int t=0; for(int j=i;j;j=f[j]) if(s[i]==s[j]) // 相等才累加; ++t; cnt=(cnt+t)%mod; } cout<<cnt<<endl; } return 0; }
2.上面的是正版的KMP...对于每一个f[i]其实只是一个试探可能性,并不确定是否相等;那么我们就利用前面的相等的f[i]来确定与当前位相等的f[i],这样就不需要病了f[i]来找是否p[i] = p[f[i]]了,并且这是一个基础,即一个子结构。用一个数组记录下前一个p[f[i]]的前缀串,直接+1即可;
62ms,时间复杂度为O(n)
#include<bits/stdc++.h> using namespace std; const int N = 2e5+7; const int mod = 10007; char p[N]; int f[N],dp[N]; void getfail() { int j=0,n=strlen(p+1); f[1]=0; for(int i = 2;i <= n;i++){ while(j && p[j+1] != p[i]) j = f[j];//确定当前位置是前面前缀串的最后一位; if(p[i] == p[j+1]) j++; f[i] = j; } } int main() { int n,T; scanf("%d",&T); while(T--){ scanf("%d",&n); scanf("%s", p+1); getfail(); int ans = 0; dp[0] = 0; for(int i = 1;i <= n;i++){ dp[i] = dp[f[i]] + 1; ans = (ans+dp[i])%mod; } printf("%d\n",ans); } return 0; }
hdu 3336 Count the string KMP+DP优化
原文:http://www.cnblogs.com/hxer/p/5268135.html