标签:
Description
对于两个字符串a,b,定义a*b为将b接到a的末尾组成新的字符串。对于一个字符串a的幂运算的定义与我们在数学中的定义一样:a^0=‘‘(空字符),a^(n+1)=(a^n)*a。
Input
输入数据每一行为一个字符串,长度为L(1<=L<=1000000)。输入数据以‘.‘结尾。
Output
对于每个字符串s,输出最大的n使得字符串s满足条件:s=a^n(a为一个字符串)。
Sample Input
abcd
aaaa
ababab
.
Sample Output
1
4
3
Solution
题意就是给你一个字符串,求这个字符串是为哪个子串循环复制而成的,要求子串循环复制的次数最大。
因为是字符串,而且需要自我匹配,就会想到kmp的next[]。
然后通过一些模拟后发现,如果一个字符串s是有其长度为l的子串a循环复制而成的,则将s左移或右移l为后得到s‘,s‘与s在第1...n-l位依然重合(如下图)。
还有一个需要考虑的是,l必须为s的因数,否则无法形成s。
到这里,问题就基本解决了,具体细节参见代码。
1 #include<set> 2 #include<cmath> 3 #include<ctime> 4 #include<queue> 5 #include<stack> 6 #include<cstdio> 7 #include<vector> 8 #include<string> 9 #include<cstring> 10 #include<cstdlib> 11 #include<iostream> 12 #include<algorithm> 13 #define N 1000002 14 using namespace std; 15 int next[N],l[N],n,ans; 16 char a[N]; 17 inline void get_next(){ 18 for(int i=2,j=0;i<=n;i++){ 19 while(j&&a[i]!=a[j+1]) j=next[j]; 20 j+=(a[i]==a[j+1]); 21 next[i]=j; 22 } 23 } 24 inline bool chk(int k){ 25 return !(n%(n-k)); 26 } 27 inline void init(){ 28 while(true){ 29 scanf("%s",a+1); 30 n=strlen(a+1); 31 if(n==1&&a[1]==‘.‘) break; 32 fill(next+1,next+1+n,0); 33 get_next(); 34 for(ans=next[n];ans;ans=next[ans]) 35 if(chk(ans)) break; 36 ans=n-ans; 37 printf("%d\n",n/ans); 38 } 39 } 40 int main(){ 41 freopen("pow.in","r",stdin); 42 freopen("pow.out","w",stdout); 43 init(); 44 fclose(stdin); 45 fclose(stdout); 46 return 0; 47 }
标签:
原文地址:http://www.cnblogs.com/AireenYe/p/5583584.html