/*
给定一个长度为n的字符串s,求它的每个前缀的 最短循环节。换句话说,对于每个i (2<=i<=n),
求一个最大的整数K>1 (如果K存在),使得S的前i个字符组成的前缀是某个字符串重复K次得到
的。输出所有存在K的i和对应的K。
给定一个长度为n的字符串s,求它的每个前缀的 最短循环节。换句话说,对于每个i (2<=i<=n),
求一个最大的整数K>1 (如果K存在),使得S的前i个字符组成的前缀是某个字符串重复K次得到
的。输出所有存在K的i和对应的K。
比如对于字符串aabaabaabaab, 只有当i=2,6,9,12时K存在,且分别为2,2,3,4
用的 是很不常见的 MP 算法(其实就是个状态转移图的构造)
*/
Problem : 1358 ( Period ) Judge Status : Accepted
RunId : 7623334 Language : C++ Author : CherryChou
Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta
RunId : 7623334 Language : C++ Author : CherryChou
Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta
#include<functional> #include<algorithm> #include<iostream> #include<fstream> #include<sstream> #include<iomanip> #include<numeric> #include<cstring> #include<cassert> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<stack> #include<cmath> #include<ctime> #include<list> #include<set> #include<map> using namespace std; const int MAXN=1000015; char T[MAXN]; int F[MAXN]; void getfail(char *P,int *f)// MP算法 { f[0]=f[1]=0; int m=strlen(P); for(int i=1;i<m;i++){ int j=f[i]; while(j&&P[i]!=P[j]) j=f[j]; f[i+1]=(P[i]==P[j]?j+1:0); } } int main(){ int len,cnt=0; while(~scanf("%d%*c",&len),len){ printf("Test case #%d\n",++cnt); scanf("%s",T); getfail(T,F); for(int i=2;i<=len;i++){ if(F[i]>0&&i%(i-F[i])==0){ printf("%d %d\n",i,i/(i-F[i])); } } puts(""); } return 0; }
Source Code
Problem: 1961 | User: imutzcy | |
Memory: 5028K | Time: 188MS | |
Language: C++ | Result: Accepted |
- Source Code
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1000000 + 10; char str[maxn]; int next[maxn]; int n; void get_next() { int j,k; j=0;k=-1;next[0]=-1; while(str[j]!='\0') { if(k==-1||str[j]==str[k]) { j++; k++; if(j%(j-k)==0&&j/(j-k)>1) printf("%d %d\n",j,j/(j-k)); next[j]=k; } else k=next[k]; } } int main() { int text=0; while(~scanf("%d",&n),n) { scanf("%s",str); printf("Test case #%d\n",++text); get_next(); printf("\n"); } return 0; }