KMP算法
先来个模版:(P3375)
#include<cstdio> #include<cstring> const int N=1000010; char a[N],b[N]; int lena,lenb,next[N]; void init() { int j=0;next[1]=0; for(int i=2;i<=lenb;i++) { while(j&&b[j+1]!=b[i]) j=next[j]; if(b[j+1]==b[i]) j++; next[i]=j; } } void sovle() { int j=0; for(int i=1;i<=lena;i++) { while(j&&b[j+1]!=a[i]) j=next[j]; if(b[j+1]==a[i]) j++; if(j==lenb) printf("%d\n",i-lenb+1); } } int main() { scanf("%s %s",a+1,b+1); lena=strlen(a+1),lenb=strlen(b+1); init(); sovle(); for(int i=1;i<=lenb;i++) printf("%d ",next[i]); return 0; }
接下来是题:
一:51nod 1277 字符串中的最大值:
求个next数组,然后dp;
#include<cstdio> #include<cstring> const int N=100010; char map[N]; int next[N]; int len; long long ans[N]; void init() { int j=0;next[1]=0; for(int i=2;i<=len;i++) { while(j&&map[j+1]!=map[i]) j=next[j]; if(map[j+1]==map[i]) j++; next[i]=j; } } int main() { scanf("%s",map+1); len=strlen(map+1); init(); // for(int i=1;i<=len;i++) printf("%d ",next[i]); long long maxx=0; for(int i=len;i>=1;i--) { ans[i]++; ans[next[i]]+=ans[i]; if(maxx<ans[i]*i) maxx=ans[i]*i; } printf("%lld",maxx); return 0; }
二:bzoj 3670: [Noi2014]动物园
同上,关键是dp方程;
#include<cstdio> #include<cstring> const int N=1000010; const int mod=1e9+7; char map[N]; int next[N],num[N],len=0; long long ans; inline void getnext() { int j=0;next[1]=0; for(int i=2;i<=len;i++) { while(j&&map[j+1]!=map[i]) j=next[j]; if(map[j+1]==map[i]) j++; next[i]=j; num[i]=num[j]+1; } } inline void getnum() { int j=0; for(int i=2;i<=len;i++) { while(j&&map[j+1]!=map[i]) j=next[j]; if(map[j+1]==map[i]) j++; while(j<<1>i) j=next[j]; ans=(ans*(num[j]+1))%mod; } printf("%lld\n",ans); } int main() { int t; scanf("%d",&t); while(t--) { memset(next,0,sizeof(next)); memset(map,0,sizeof(map)); memset(num,0,sizeof(num)); len=0; num[1]=1; scanf("%s",map+1); len=strlen(map+1); getnext(); //for(int i=1;i<=len;i++) printf("%d ",next[i]); ans=1; getnum(); // for(int i=1;i<=len;i++) printf("%d ",num[i]); } return 0; }
总结:kmp上来就是打个next数组表,然后推dp方程;
这里推荐个csdn博客:关于KMP算法