CodeForces 432D Prefixes and Suffixes
思路
首先求出原串的 \(\mathbf{Z}\) 函数数组 \(nxt\),那么长度为 \(n - i + 1\) 的前后缀满足要求当且仅当 \(i + nxt_i - 1 = n\)。
显然长度为 \(i\) 的前缀的出现次数为满足 \(nxt_j \ge i\) 的 \(j\) 的个数,差分 + 后缀和维护即可。
时间复杂度 \(O(|s|)\)。
代码
code
/*
p_b_p_b txdy
AThousandMoon txdy
AThousandSuns txdy
hxy txdy
*/
#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 100100;
int n, nxt[maxn], f[maxn];
char s[maxn];
void solve() {
scanf("%s", s + 1);
n = strlen(s + 1);
nxt[1] = n;
for (int i = 2, l = 0, r = 0; i <= n; ++i) {
nxt[i] = (i > r) ? 0 : min(nxt[i - l + 1], r - i + 1);
while (s[nxt[i] + 1] == s[nxt[i] + i]) {
++nxt[i];
}
if (i + nxt[i] - 1 > r) {
l = i;
r = i + nxt[i] - 1;
}
}
for (int i = 1; i <= n; ++i) {
++f[nxt[i]];
}
for (int i = n; i; --i) {
f[i] += f[i + 1];
}
vector<pii> ans;
for (int i = 1; i <= n; ++i) {
if (i + nxt[i] - 1 == n) {
ans.pb(make_pair(nxt[i], f[nxt[i]]));
}
}
sort(ans.begin(), ans.end());
printf("%d\n", (int)ans.size());
for (pii p : ans) {
printf("%d %d\n", p.fst, p.scd);
}
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}