KMP算法
poj3461 Oulipo
题目大意:模板题。
思路:模板题。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int f[10010],ans; char s1[10000],s2[1000000]; void prework() { int i,j,n; n=strlen(s1); f[0]=f[1]=0; for (i=1;i<n;++i) { j=f[i]; while(j&&s1[i]!=s1[j]) j=f[j]; f[i+1]=(s1[j]==s1[i]?j+1:0); } } void work() { int n,m,i,j; n=strlen(s1);m=strlen(s2); j=0; for (i=0;i<m;++i) { while(j&&s1[j]!=s2[i]) j=f[j]; if (s1[j]==s2[i]) ++j; if (j==n) ++ans; } } int main() { int i,n; scanf("%d",&n); for (i=1;i<=n;++i) { scanf("%*c%s%*c%s",&s1,&s2); prework(); ans=0;work(); printf("%d\n",ans); } }
poj2752 Seek the Name, Seek the Fame
题目大意:求一个串前缀和后缀完全一样的所有长度。
思路:维护出f数组后,从最后一位循环一下,如果ch[j]==ch[f[j]],f[j]+1就是一个可行的长度,j=f[j],一直循环下去。突然发现f数组很神奇。其实我们能保证前f[j]+1个元素和以j为结尾的f[j]+1个元素一定是相等的。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char ch[400000]; int f[400001]={0},ans[400001]={0},l; void prework() { int i,j; f[0]=f[1]=0; for (i=1;i<l;++i) { j=f[i]; while(j&&ch[i]!=ch[j]) j=f[j]; f[i+1]=(ch[i]==ch[j]?j+1:0); } } void work() { int j; j=l-1; while(j&&ch[j]==ch[f[j]]) { ans[++ans[0]]=f[j]+1; j=f[j]; } } int main() { int i,j,n; while(scanf("%s",&ch)==1) { ans[0]=0;l=strlen(ch); ans[++ans[0]]=l; prework(); work(); for (i=ans[0];i;--i) printf("%d ",ans[i]); printf("\n"); } }
poj2406 Power Strings
题目大意:子串重复出现次数最多且重复后恰好是原串的长度。
思路:如果能重复后恰是原串的长度,那么l%(l-f[l])==0,如果能==0,则答案就是l/(l-f[l]),否则答案为1。这里一定是l和f[l],否则会出很多奇怪的问题。。。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char ch[1000000]; int f[1000001]={0},l; void prework() { int i,j; f[0]=f[1]=0; for (i=1;i<l;++i) { j=f[i]; while(j&&ch[i]!=ch[j]) j=f[j]; f[i+1]=(ch[i]==ch[j]?j+1:0); } } int main() { int i,j,ans; while(scanf("%s",&ch)==1) { l=strlen(ch); if (ch[0]==‘.‘) break; prework(); if (l%(l-f[l])==0) ans=l/(l-f[l]); else ans=1; printf("%d\n",ans); } }
时间: 2024-10-20 21:20:38