Description
Given two strings a and b we define ab to be their concatenation. For example, if a = “abc” and b = “def” then ab = “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
Hint
This problem has huge input, use scanf instead of cin to avoid time limit exceed.
法一:可以利用KMP的最小循环节的性质求解
对于str2,cyc = len2 - next[len2]是它的最小循环节长度.
如果len2 % cyc == 0,表示str2能够由完整的几个循环节组成,输出len2 / cyc。
如果len2 % cyc != 0,说明最后不是一个完整的循环节。在这道题里面就需要直接输出1,表示它自己由它本身这样一个循环节组成,而不是len2 / cyc。
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int n=1e6;
int next[n+5];
char str1[n+5],str2[n+5];
int len1,len2;
void get_next()//求next数组
{
int i1=0,i2=-1;
next[0]=-1;
while(i1<len2)//遍历完str2时结束
{
if(i2==-1||str2[i1]==str2[i2])//如果是str2中下标为1的元素,或者能够匹配上
next[++i1]=++i2;
else//不能匹配上,回跳
i2=next[i2];
}
}
int main(void)
{
int cyc;
while(scanf("%s",str2)!=EOF&&strcmp(str2,".")!=0)
{
len2=strlen(str2);
get_next();
cyc=len2-next[len2];//循环节
if(len2%cyc==0)
printf("%d\n",len2/cyc);
else
printf("1\n");
}
return 0;
}
法二:利用hash算法来求解
yfy同学的代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
const int N=1000100,P=131;
int n,m,len;
char str[N];
LL p[N],h[N];
int mod=10009;
LL cal(int x,LL y)
{
LL re=1;
while(x)
{
if(x&1)
{
re=(re*y)%mod;
}
x>>=1;
y=(y*y)%mod;
}
return re;
}
bool check(int x)
{
LL cc=cal(x,LL(P));
for(int i=x;i<=len;i+=x)
{
if(h[x]!=(h[i]-(h[i-x]*cc)%mod+mod)%mod)
{
return false;
}
}
return true;
}
int main(void)
{
while(scanf("%s",str+1) != EOF && str[1] != '.')
{
len=strlen(str+1);
for(int i=1;i<=len;i++)
{
h[i]=(h[i-1]*P+str[i])%mod;
}
int flag=0;
// 枚举循环节长度
for(int i=1;i<=len;i++)
{
if(len%i==0&&check(i))
{
printf("%d\n",len/i);
flag = 1;
break;
}
}
if(flag==0)
printf("1\n");
}
return 0;
}