问题描述:给定一个字符串L,已知这个字符串是由某个字符串S重复R次而得到的, 求R的最大值。
方法一:直接暴力枚举子串长度,从1到len/2一一判断,如果合法即进行输出。
#include<stdio.h>
#include<string.h>
int main()
{
char s[1000000+100];
int i,j,k,len,ok;
while(scanf("%s",s))
{
if(s[0]=='.')
break;
len=strlen(s);
for(i=0;i<len;i++)//枚举每个子串是从0到i
{
ok=1;
if(len%(i+1)!=0)
continue;
for(j=0;j<=i;j++)//之后进行判断每个小段是否相同即可
{
for(k=1;k<len/(i+1);k++)
if(s[j]!=s[j+k*(i+1)])
{
ok=0;
break;
}
if(!ok)
break;
}
if(ok)
{
printf("%d\n",len/(i+1));
break;
}
}
if(!ok)
printf("1\n");
}
return 0;
}
方法二:利用KMP的next值来进行计算(我也不太懂,也是看的题解才A掉)
设子串长度为len,则根据next值的定义可以得到:len-next[i]即为每次失配后需要移动的距离。如果len能够整除len-next[len],那么len-next[len]就代表最小重复单元的长度。
#include<stdio.h>
#include<string.h>
char s[1000010];
int len,i,j,k;
int next[1000010];
void kmp1(void)
{
int i,j;
j=-1;
next[0]=-1;
for (i=1;i<=len;i++)
{
while (j>-1&&s[j+1]!=s[i])
j=next[j];
if (s[j+1]==s[i])
j++;
next[i]=j;
}
}
int main()
{
while(scanf("%s",s))
{
if(s[0]=='.')
break;
len=strlen(s);
kmp1();
if(len%(len-1-next[len-1])==0)
printf("%d\n",len/(len-1-next[len-1]));
else
printf("1\n");
}
}