ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)
Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).
Input
Each test case is a line of input representing s, a string of printable characters.
<b< dd="">
Output
For each s you should print the largest n such that s = a^n for some string a. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.
Sample Input
abcd
aaaa
ababab
.
Sample Output
1
4
3
求最大循环长度。
KMP可以求,之前做过,见。
http://www.cnblogs.com/hua-dong/p/8016873.html
http://www.cnblogs.com/hua-dong/p/8016916.html
这里实现了后缀数组(不过好像被卡了,只能同KMP实现)。
#include<cmath> #include<cstdio> #include<string> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> int min(int x,int y) { if(x<y) return x;return y;} using namespace std; const int maxn=1000010; char ch[maxn]; struct SA { int Rank[maxn],sa[maxn],tsa[maxn],A[maxn],cntA[maxn],B[maxn],cntB[maxn]; int ht[maxn],Min[maxn][30],N; void get_SA() { N=strlen(ch+1); for(int i=0;i<=300;i++) cntA[i]=0; for(int i=1;i<=N;i++) cntA[ch[i]]++; for(int i=1;i<=300;i++) cntA[i]+=cntA[i-1]; for(int i=N;i>=1;i--) sa[cntA[ch[i]]--]=i; Rank[sa[1]]=1; for(int i=2;i<=N;i++) Rank[sa[i]]=Rank[sa[i-1]]+(ch[sa[i]]==ch[sa[i-1]]?0:1); for(int l=1;Rank[sa[N]]<N;l<<=1){ for(int i=1;i<=N;i++) cntA[i]=cntB[i]=0; for(int i=1;i<=N;i++) cntA[A[i]=Rank[i]]++; for(int i=1;i<=N;i++) cntB[B[i]=i+l<=N?Rank[i+l]:0]++; for(int i=1;i<=N;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1]; for(int i=N;i>=1;i--) tsa[cntB[B[i]]--]=i; for(int i=N;i>=1;i--) sa[cntA[A[tsa[i]]]--]=tsa[i]; Rank[sa[1]]=1; for(int i=2;i<=N;i++) Rank[sa[i]]=Rank[sa[i-1]]+(A[sa[i]]==A[sa[i-1]]&&B[sa[i]]==B[sa[i-1]]?0:1); } } void get_hgt() { for(int i=1,j=0;i<=N;i++){ if(j) j--; while(ch[i+j]==ch[sa[Rank[i]-1]+j]) j++; ht[Rank[i]]=j; } } void get_rmq() { for(int i=1;i<=N;i++) Min[i][0]=ht[i]; for(int i=1;(1<<i)<=N;i++) for(int j=1;j+(1<<i)-1<=N;j++){ Min[j][i]=min(Min[j][i-1],Min[j+(1<<(i-1))][i-1]); } } int query_rmq(int L,int R) { if(L>R) swap(L,R);L++; int k=log2(R-L+1); return min(Min[L][k],Min[R-(1<<k)+1][k]); } void solve() { int ans=1; for(int i=1;i<=N;i++){ if(N%i!=0) continue; if(i+query_rmq(Rank[1],Rank[1+i])==N) { ans=N/i; break; } } printf("%d\n",ans); } }Sa; int main() { while(~scanf("%s",ch+1)){ if(ch[1]=='.') return 0; Sa.get_SA(); Sa.get_hgt(); Sa.get_rmq(); Sa.solve(); } return 0; }