题意
给出一个字符串S,对S的每一个前缀,如果它的最小循环元的最大循环次数大于1,我们就输出这个前缀的位置和最大循环次数。
思路
我们可以利用KMPKMPKMP算法中的nextnextnext数组的性质发现,S[1S[1S[1$next[i]]=S[i-next[i]+1$i]i]i],且不存在更大的nextnextnext。当i−next[i]i-next[i]i−next[i]能整除iii时,那么S[1S[1S[1$next[i]]$就是$S[1$i]i]i]的最小循环元了,i/(i−next[i])i/(i-next[i])i/(i−next[i])就是最大循环次数。
代码
#include<cstdio>
#include<cstring>
using namespace std;
int n,t,next[1000001];
char s[1000001];
void calc_next() {
next[1]=0;
int j=0;
for (int i=2;i<=n;i++) {
while (j&&s[i]!=s[j+1]) j=next[j];
if (s[i]==s[j+1]) j++;
next[i]=j;
}
}
int main() {
while (scanf("%d",&n)&&n) {
scanf("%s",s+1);
calc_next();
printf("Test case #%d\n",++t);
for (int i=2;i<=n;i++)
if (i%(i-next[i])==0&&i/(i-next[i])>1)
printf("%d %d\n",i,i/(i-next[i]));
printf("\n");
}
}