SP687 REPEATS - Repeats
XXII. SP687 REPEATS - Repeats
借用优秀的拆分的套路,直接枚举循环节长度
Sol 1:显然答案满足可二分性。二分
Sol 2:Sol 1 太不优美了。
Sol 3:Sol 2 仍不够优美。根据 border 论最经典结论,
#include <bits/stdc++.h>
using namespace std;
constexpr int K = 16;
constexpr int N = 5e4 + 5;
int n, lg[N];
char s[N];
struct SA {
int sa[N], rk[N], ork[N], buc[N], id[N], mi[K][N];
bool cmp(int a, int b, int w) {return ork[a] == ork[b] && ork[a + w] == ork[b + w];}
void build(char *s) {
int m = 1 << 7, p = 0;
memset(buc, 0, sizeof(buc));
memset(rk, 0, sizeof(rk));
for(int i = 1; i <= n; i++) buc[rk[i] = s[i]]++;
for(int i = 1; i <= m; i++) buc[i] += buc[i - 1];
for(int i = n; i; i--) sa[buc[rk[i]]--] = i;
for(int w = 1; ; w <<= 1, m = p, p = 0) {
for(int i = n - w + 1; i <= n; i++) id[++p] = i;
for(int i = 1; i <= n; i++) if(sa[i] > w) id[++p] = sa[i] - w;
memset(buc, 0, sizeof(buc));
memcpy(ork, rk, sizeof(rk));
p = 0;
for(int i = 1; i <= n; i++) buc[rk[id[i]]]++;
for(int i = 1; i <= m; i++) buc[i] += buc[i - 1];
for(int i = n; i; i--) sa[buc[rk[id[i]]]--] = id[i];
for(int i = 1; i <= n; i++) rk[sa[i]] = cmp(sa[i], sa[i - 1], w) ? p : ++p;
if(p == n) break;
}
for(int i = 1, k = 0; i <= n; i++) {
if(k) k--;
while(s[i + k] == s[sa[rk[i] - 1] + k]) k++;
mi[0][rk[i]] = k;
}
for(int i = 1; i <= lg[n]; i++)
for(int j = 1; j + (1 << i) - 1 <= n; j++)
mi[i][j] = min(mi[i - 1][j], mi[i - 1][j + (1 << i - 1)]);
}
int lcp(int i, int j) {
if((i = rk[i]) > (j = rk[j])) swap(i, j);
int d = lg[j - (i++)];
return min(mi[d][i], mi[d][j - (1 << d) + 1]);
}
} sa, rev;
void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
s[i] = getchar();
while(!isalpha(s[i])) s[i] = getchar();
}
s[n + 1] = 0;
sa.build(s);
reverse(s + 1, s + n + 1);
rev.build(s);
int ans = 1;
for(int L = 1; L <= n; L++)
for(int p = L, q = L + L; q <= n; p += L, q += L) {
int r = sa.lcp(p, q), l = rev.lcp(n - q + 1, n - p + 1);
ans = max(ans, (l + r - 1) / L + 1);
}
cout << ans << endl;
}
int main() {
#ifdef ALEX_WEI
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
for(int i = 2; i < N; i++) lg[i] = lg[i >> 1] + 1;
int T;
cin >> T;
while(T--) solve();
return 0;
}
/*
2022/6/16
start coding at 18:58
finish debugging at 19:23
*/