题意:(训练指南P213) 求每个前缀的最短循环节
分析:利用失配函数的性质,如果i % (i - fail[i]) == 0,那么正好错位移动一个循环节长度。
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 5; char str[N]; int fail[N]; int len; void get_fail(char *P) { int i = 0, j = -1; fail[i] = j; while (i < len) { if (j == -1 || P[j] == P[i]) { fail[++i] = ++j; } else j = fail[j]; } } int main(void) { int cas = 0; while (scanf ("%d", &len) == 1) { if (!len) break; scanf ("%s", &str); get_fail (str); for (int i=0; i<=len; ++i) { printf ("%d ", fail[i]); } puts (""); printf ("Test case #%d ", ++cas); for (int i=1; i<=len; ++i) { if (fail[i] >= 0 && i % (i - fail[i]) == 0) { int k = i / (i - fail[i]); if (k > 1) { printf ("%d %d ", i, k); } } } puts (""); } return 0; }