【POJ2406】Power Strings-KMP中next数组的应用

测试地址: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
",len%(len-next[len-1])==0?len/(len-next[len-1]):1);
  }
  
  return 0;
}