题意大概是,给你一个字符串,如果该字符串的某一个前缀Si是由若干个相同的字符串循环构成,就输出i和最短循环节长度
利用KMP算法里面失配函数可以解决这个问题,失配函数f(i)可以定义为字符串的前缀Si-1中最长的与真前缀相等的真后缀的长度。
如果当前字符串是由若干个字符串循环构成的话,必然有最长真后缀的长度加上最短循环节(也就是字符串开头的第一个循环节)长度的和应该恰好等于i
#include <cstdio> #include <cstring> using namespace std; const int maxn = 1000005; char str[maxn]; int f[maxn]; inline void getfail() { int m = strlen(str); f[0] = f[1] = 0; for(int i = 2;i <= m;i++) { int j = f[i - 1]; while(j && str[i - 1] != str[j]) j = f[j]; if(str[i - 1] == str[j]) f[i] = j + 1; else f[i] = 0; } } int main() { int n,kase = 0; while(scanf("%d",&n),n) { printf("Test case #%d ",++kase); scanf("%s",str); getfail(); for(int i = 1;i <= n;i++) { if(f[i] > 0 && i % (i - f[i]) == 0) { printf("%d %d ",i,i / (i - f[i])); } } putchar(' '); } return 0; }