UVA1328题解
前置知识:KMP
本蒟蒻已经默认大佬们会了 KMP
我们来看一下这道题:
设 $nxt_i$ 表示 $A$ 中以 $i$ 为结尾的非前缀子串与 $A$ 的前缀 能够匹配的最长长度,即:
$nxt_i = \max(j)$,其中 $j < i$ 并且 $A_{i - j + 1}$ ~ $A_i = A_1$ ~ $A_j$
$nxt_i$是 KMP 的精髓,不在讲述。
显然,若 $i - nxt_i$ 能被 $i$ 整除时, $A_1$ ~ $A_{nxt_i}$ 就是 $A_1$ ~ $A_i$ 的最小循环元,那么它的最大循环次数是 $i / (i - nxt_i)$。
其中,$i - nxt_i$ 能整除 $i$ 的条件是为了保证循环元每次重复的完整性
具体实现,请看代码。
#include <iostream>
using namespace std;
const int maxn = 1000010;
char a[maxn];
int nxt[maxn], n, t;
void calc () {
nxt[1] = 0;
for (int i = 2, j = 0; i <= n; ++i) {
while (j > 0 && a[i] != a[j + 1]) j = nxt[j];
if (a[i] == a[j + 1]) j ++;
nxt[i] = j;
}
}
int main() {
while (scanf ("%d", &n) != EOF && n) {
scanf ("%s", a + 1);
calc (); // 计算 nxt[i]
printf ("Test case #%d\n", ++t);// 注意输出
for (int i = 2; i <= n; ++i) {
if (i % (i - nxt[i]) == 0 && i / (i - nxt[i]) > 1) {
printf ("%d %d\n", i, i / (i - nxt[i]));
}
}
printf ("\n");
}
return 0;
}