可以发现这份代码中枚举前缀的部分 for 循环的方向反了(正确的方向应该是从 ⌊n/2⌋ 到 1),然后 SAM 的字符集大小开的 4,结果它过了?
这说明什么?洛谷精心脚造数据,让合法方案唯一,且字符集 {a,b,c,d}?
#include <bits/stdc++.h>
using namespace std;
#define rep(i, f, t) for (int i = (f), ed##i = (t); i <= ed##i; ++i)
#define re(i, t) rep (i, 1, t)
#define nxt(i, f, g) for (int i = g.h[f]; i; i = g.e[i].n)
template <class T, class E>
__attribute__((always_inline)) inline void up(T &x, E &&y) {
if (x < y) x = y;
}
const int N = 2e6 + 9;
int n, ed[N], dfn[N], tp[N], sz[N], dep[N], tim, son[N], ans;
char s[N];
struct G {
int h[N], tot;
struct E {
int t, n;
} e[N];
inline void Add(int f, int t) { e[++tot] = {t, h[f]}, h[f] = tot; }
} g;
struct SAM {
struct T {
int e[4], len, lk;
} d[N];
int lst, tot;
inline void Init() { d[lst = ++tot].lk = 0; }
inline int Add(int c) {
if (d[lst].e[c] && d[d[lst].e[c]].len == d[d[lst].e[c]].len + 1) return d[lst].e[c];
int cur = ++tot, p = lst, cl;
d[cur].lk = 1, d[cur].len = d[lst].len + 1;
while (p && !d[p].e[c]) {
d[p].e[c] = cur;
p = d[p].lk;
}
bool fl = 0;
if (p) {
int q = d[p].e[c];
if (d[p].len + 1 == d[q].len)
d[cur].lk = q;
else {
if (p == lst) fl = 1;
cl = ++tot;
d[cl] = d[q], d[cl].len = d[p].len + 1;
while (p && d[p].e[c] == q) d[p].e[c] = cl, p = d[p].lk;
d[cur].lk = d[q].lk = cl;
}
}
return lst = (fl ? cl : cur);
}
} sam;
void Dfs1(int f) {
dep[f] = dep[sam.d[f].lk] + 1;
sz[f] = 1;
nxt (i, f, g) {
int t = g.e[i].t;
Dfs1(t), sz[f] += sz[t];
if (sz[t] > sz[son[f]]) son[f] = t;
}
}
void Dfs2(int f) {
dfn[f] = ++tim;
if (!son[f]) return;
tp[son[f]] = tp[f], Dfs2(son[f]);
nxt (i, f, g) {
int t = g.e[i].t;
if (t == son[f]) continue;
tp[t] = t, Dfs2(t);
}
}
inline int Lca(int u, int v) {
while (tp[u] != tp[v]) dep[tp[u]] > dep[tp[v]] ? u = sam.d[tp[u]].lk : v = sam.d[tp[v]].lk;
return dep[u] > dep[v] ? v : u;
}
inline bool Ck(int l1, int l2, int len) {
if (l1 <= 0 || l2 <= 0) return 0;
int r1 = l1 + len - 1, r2 = l2 + len - 1;
if (r1 > n || r2 > n) return 0;
if (l2 <= r1) return 0;
int lca = Lca(ed[r1], ed[r2]);
return sam.d[lca].len >= len;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> (s + 1);
sam.Init();
re (i, n)
ed[i] = sam.Add(s[i] - 'a');
rep (i, 2, sam.tot)
g.Add(sam.d[i].lk, i);
Dfs1(1), tp[1] = 1, Dfs2(1);
int now = n;
re (i, n / 2) {
now += 2;
if (!Ck(1, n - i + 1, i)) continue;
while (!Ck(i + 1, n - i - now + 1, now)) --now;
up(ans, i + now);
}
cout << ans << '\n';
return 0;
}