测试地址:Power Strings
题目大意:给定一个字符串S,S由某一个子串X重复多次构成(即S=XXX...),求重复的最多次数。
做法:做了这一道题才发现KMP除了拿来做字符串匹配,还是有很多其他作用的...
这一道题乍一看没有什么思路,但其实想到KMP中next数组的定义,我们可以得出一个结论:如果S由某一子串X重复多次构成,那么next[len(S)-1](此处下标从0开始)=len(S)-len(X),进一步得出len(X)=len(S)-next[len(S)-1]。但是这不是最终的结论,看这样一个例子:abababa,计算出next[len(S)-1]=5,但显然该字符串只能由该字符串本身重复一次构成,仔细观察我们就可以知道,按上述计算,len(X)=len(S)-next[len(S)-1]=2,然而len(S)%len(X)!=0,所以可以判定结果为1。这样我们就可以得出完整的结论:首先用KMP算出next数组,然后按照上述算法求出len(X),判断:如果len(S)%len(X)==0,那么该情况合法,答案即为len(S)/len(X),否则答案为1。
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
char s[1000010];
int next[1000010],len;
void calc_next()
{
next[0]=0;
for(int i=1;i<len;i++)
{
int index=next[i-1];
while(index!=0&&s[i]!=s[index]) index=next[index-1];
if (s[i]!=s[index]) next[i]=0;
else next[i]=index+1;
}
}
int main()
{
while(1)
{
scanf("%s",s);
len=strlen(s);
if (s[0]=='.') break;
calc_next();
printf("%d\n",len%(len-next[len-1])==0?len/(len-next[len-1]):1);
}
return 0;
}