题意:给一个长度为n的串,求出它所有是”periodic string”的前缀子串,”periodic string”是任意一个串的循环。输出”periodic string”的长度和循环次数。
思路:想了好久发现还是利用KMP里面next数组的性质。
举例子可以看出,如果到i位置的前缀是周期串,那么就有 (i + 1) % [(i + 1)-(next[i] + 1)] == 0。通过next数组前缀等于当前后缀的性质可以推出来。另外要排除next[i]等于-1的情况。想不明白可以参考http://www.cnblogs.com/wuyiqi/archive/2012/01/06/2314078.html
C++里不能命名next的全局变量,CE好几发才发现。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const int maxn=1000005;
typedef long long ll;
int nxt[maxn];
char s[maxn];
void get_next(){
int len = strlen(s);
nxt[0] = -1;
int index;
for(int i=1; i<len; ++i){
index = nxt[i - 1];
while(index >= 0 && s[i] != s[index + 1]){
index = nxt[index];
}
if(s[i] == s[index + 1]){
nxt[i] = index + 1;
} else {
nxt[i] = -1;
}
}
}
int main(){
int n, cas = 0;
while(~scanf("%d", &n) && n){
scanf("%s", s);
get_next();
printf("Test case #%d\n", ++cas);
for(int i=1; i<n; ++i){
if(nxt[i] != -1 && (i + 1) % (i - nxt[i]) == 0){
printf("%d %d\n", i + 1, (i + 1) / (i - nxt[i]));
}
}
printf("\n");
}
return 0;
}