對字串 S 的每個前綴(長度 2~N),判斷是否為週期字串(即 A^K, K>1)。若是,輸出長度與最大 K。N ≤ 1,000,000。
KMP fail[i] = 長度為 i 的前綴最長真前綴後綴長度。
若 i % (i - fail[i]) == 0 且 fail[i] > 0,則前綴由長度 i - fail[i] 的子串重複 K = i / (i - fail[i]) 次構成。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000010;
int fail[MAXN];
char s[MAXN];
void build_fail() {
int n = strlen(s);
fail[0] = fail[1] = 0;
for (int i = 1; i < n; i++) {
int j = fail[i];
while (j && s[i] != s[j]) j = fail[j];
fail[i+1] = (s[i] == s[j]) ? j + 1 : 0;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, tc = 0;
while (cin >> n >> s, n) {
build_fail();
cout << "Test case #" << ++tc << '\n';
for (int i = 2; i <= n; i++) {
int period = i - fail[i];
if (i % period == 0 && fail[i] > 0)
cout << i << ' ' << i / period << '\n';
}
cout << '\n';
}
return 0;
}
輸入: 3 aaa 12 aabaabaabaab 0 輸出: Test case #1 2 2 3 3 Test case #2 2 2 6 2 9 3 12 4
fail[i] 表示長度 i 前綴的最長邊界長度i % (i - fail[i]) == 0 且 fail[i] > 0