Power Strings
Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 47786 Accepted: 19910
Description
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. 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.
Output
For each s you should print the largest n such that s = a^n for some string a.
Sample Input abcd aaaa ababab .
Sample Output 1 4 3
【分析】 后缀数组…倍增会挂掉(然而我只会倍增) 放一个TLE的代码(自测数据没什么问题…但扛不住100W)
【代码】
//poj 2406 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define M(a) memset(a,0,sizeof a) #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; const int mxn=1000005; int n,len,m; int sa[mxn],rank[mxn],height[mxn],x[mxn],a[mxn],y[mxn],b[mxn],mn[mxn]; char s[mxn]; inline bool comp(int i,int j,int l) { return y[i]==y[j] && (i+l>len?-1:y[i+l])==(j+l>len?-1:y[j+l]); } inline void work() { int i,j,k,p; fo(i,0,m) b[i]=0; fo(i,1,len) b[x[i]=a[i]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len;i>=1;i--) sa[b[x[i]]--]=i; for(k=1;k<=len;k<<=1) { p=0; fo(i,len-k+1,len) y[++p]=i; fo(i,1,len) if(sa[i]>k) y[++p]=sa[i]-k; fo(i,0,m) b[i]=0; fo(i,1,len) b[x[y[i]]]++; fo(i,1,m) b[i]+=b[i-1]; for(i=len;i>=1;i--) sa[b[x[y[i]]]--]=y[i]; swap(x,y),p=2,x[sa[1]]=1; fo(i,2,len) x[sa[i]]=comp(sa[i-1],sa[i],k)?p-1:p++; if(p>len) break; m=p; } p=k=0; fo(i,1,len) rank[sa[i]]=i; for(i=1;i<=len;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];a[i+k]==a[j+k];k++); } int main() { int i,j,k; while(scanf("%s",s+1)) { M(sa),M(x),M(a),M(b),M(y); memset(mn,0x3f,sizeof mn); if(s[1]=='.') return 0; len=strlen(s+1);m=129; fo(i,1,len) a[i]=s[i]; work(); mn[rank[1]]=len; for(i=rank[1]-1;i>=1;i--) //预处理每个后缀与sa[rank[1]]的lcp长度 mn[i]=min(mn[i+1],height[i+1]); for(i=rank[1]+1;i<=len;i++) mn[i]=min(mn[i-1],height[i]); fo(k,1,len-1) if(len%k==0 && mn[rank[k+1]]==len-k) { printf("%d\n",len/k); break; } if(k==len) printf("1\n"); } }