运用kmp中的next数组。
前缀中如果有周期的话,一定满足,next[i] % (i - next[i]) == 0.
满足这个条件时:
记字符串s的第i位之前的子串为p,其前缀字符串位为p.pre,后缀字符串为p.suf,以p(i,j)表示p的从i位到j - 1的字串。则i就是p的长度,next[i] 就是p.pre和p.suf的长度.
首先知道,p.pre(0,i - next[i]) = p(0, i - next[i]),因为这俩就是p的同一个子串。
又有p.pre = p.suf,所以有,p.pre(0,i - next[i]) = p.suf(0, i - next[i]).
而p.suf(0,i - next[i]) = p(i - next[i],(i - next[i]) * 2) = p.pre(i - next[i], (i - next[i]) * 2);
以此类推,可以发现p是由,p除去p.suf的子串为周期的,周期字符串。
#include<iostream>
#include<string>
using namespace std;
#define MAXN 10010000
int* cmput(int *const next, const string &s){
int ls = s.length();
int i = 0, j = -1;
next[0] = -1;
while (i < ls){
while (j >= 0 && s[i] != s[j]){
j = next[j];
}
i ++;
j ++;
next[i] = j;
}
return next;
}
int main(){
int n;
string s;
int *next = new int[MAXN];
int l;
int count = 1;
while(cin >> n){
if (!n)
return 0;
cout << "Test case #" << count++ << endl;
cin >> s;
l = s.length();
cmput(next, s);
for (int i = 2; i <= l; i ++){
if (next[i] == 0)
continue;
if (next[i] % (i - next[i]) == 0){
cout << i << ' ' << i / (i - next[i]) << endl;
}
}
cout << endl;
}
return 0;
}