using s64 = longlong; using u64 = unsignedlonglong;
/* 取 min */ template <classT> inlinevoidchmin(T &x, const T &y){ if (x > y) { x = y; } } /* 取 max */ template <classT> inlinevoidchmax(T &x, const T &y){ if (x < y) { x = y; } }
/* ----- ----- ----- 正文 ----- ----- ----- */
constint N = 100100;
int n; std::string str;
int w[N];
int root[N]; namespace trie { int NodeCount; structnode { int trans[2]; int cnt; } t[N * 32];
voidinit(){ NodeCount = 0; }
voidinsert(int &p, int q, int d, int x){ p = ++ NodeCount, t[p] = t[q], t[p].cnt ++; if (d < 0) return; int v = x >> d & 1; insert(t[p].trans[v], t[q].trans[v], d - 1, x); }
intask(int p, int q, int d, int x){ if (d < 0) return0; int v = x >> d & 1; if (t[t[q].trans[v ^ 1]].cnt - t[t[p].trans[v ^ 1]].cnt) { returnask(t[p].trans[v ^ 1], t[q].trans[v ^ 1], d - 1, x) + (1 << d); } else { returnask(t[p].trans[v], t[q].trans[v], d - 1, x); } } intask(int l, int r, int x){ returnask(root[l - 1], root[r], 16, x); } }
int ans;
namespace SA { int m; int sa[N], rk[N], height[N]; int cnt[N], id[N], px[N]; int tmprk[N * 2];
intsame(int x, int y, int k){ return tmprk[x] == tmprk[y] && tmprk[x + k] == tmprk[y + k]; }
for (int i = n + 1; i <= 2 * n; i ++) tmprk[i] = -1;
m = 256; for (int i = 1; i <= n; i ++) rk[i] = str[i];
for (int i = 1; i <= m; i ++) cnt[i] = 0; for (int i = 1; i <= n; i ++) cnt[rk[i]] ++; for (int i = 1; i <= m; i ++) cnt[i] += cnt[i - 1]; for (int i = n; i >= 1; i --) sa[cnt[rk[i]] --] = i;
for (int k = 1, p = 0; k < n; k <<= 1, m = p) { p = 0; for (int i = n - k + 1; i <= n; i ++) id[++ p] = i; for (int i = 1; i <= n; i ++) if (sa[i] > k) id[++ p] = sa[i] - k; for (int i = 1; i <= m; i ++) cnt[i] = 0; for (int i = 1; i <= n; i ++) cnt[px[i] = rk[id[i]]] ++; for (int i = 1; i <= m; i ++) cnt[i] += cnt[i - 1]; for (int i = n; i >= 1; i --) sa[cnt[px[i]] --] = id[i];
for (int i = 1; i <= n; i ++) tmprk[i] = rk[i];
p = 0; for (int i = 1; i <= n; i ++) rk[sa[i]] = same(sa[i - 1], sa[i], k) ? p : ++ p;
if (p == n) break; }
for (int i = 1, h = 0; i <= n; i ++) { if (h) h --; while (str[i + h] == str[sa[rk[i] - 1] + h]) h ++; height[rk[i]] = h; } }
int rt; structnode { int lc, rc; int L, R; } t[N];
int top, stk[N]; voidbuild_tree(){ top = 0; for (int i = 2; i <= n; i ++) { t[i].lc = t[i].rc = 0, t[i].L = t[i].R = i; }
for (int i = 2; i <= n; i ++) { int k = top; while (k && height[stk[k]] > height[i]) k --;
if (k) t[stk[k]].rc = i; if (k < top) t[i].lc = stk[k + 1];
stk[top = k + 1] = i; } rt = stk[1]; }
voidsolve(int p){ if (t[p].lc) solve(t[p].lc), chmin(t[p].L, t[t[p].lc].L); if (t[p].rc) solve(t[p].rc), chmax(t[p].R, t[t[p].rc].R);
int l = t[p].L - 1, r = t[p].R;
if (p - l < r - p + 1) { for (int i = l; i < p; i ++) { chmax(ans, height[p] + trie::ask(p, r, w[sa[i]])); } } else { for (int i = p; i <= r; i ++) { chmax(ans, height[p] + trie::ask(l, p - 1, w[sa[i]])); } } } }
using s64 = longlong; using u64 = unsignedlonglong;
/* 取 min */ template <classT> inlinevoidchmin(T &x, const T &y){ if (x > y) { x = y; } } /* 取 max */ template <classT> inlinevoidchmax(T &x, const T &y){ if (x < y) { x = y; } }
/* ----- ----- ----- 正文 ----- ----- ----- */
constint N = 100100; constint SIZE = N * 2;
int n; std::string str;
int w[N];
int root[SIZE]; std::vector<int> g[SIZE];
namespace trie { int NodeCount; structnode { int trans[2]; } t[SIZE * 32];
intcreate(){ int p = ++ NodeCount; t[p].trans[0] = t[p].trans[1] = 0; return p; }
voidinit(){ NodeCount = 0; for (int i = 1; i <= n * 2; i ++) { root[i] = 0; g[i].clear(); } }
voidinsert(int &p, int d, int x){ p = create(); if (d < 0) return; int v = x >> d & 1; insert(t[p].trans[v], d - 1, x); }
intmerge(int p, int q){ if (!p || !q) return p ^ q; t[p].trans[0] = merge(t[p].trans[0], t[q].trans[0]); t[p].trans[1] = merge(t[p].trans[1], t[q].trans[1]); return p; }
intask(int p, int d, int x){ if (d < 0) return0; int v = x >> d & 1; if (t[p].trans[v ^ 1]) { returnask(t[p].trans[v ^ 1], d - 1, x) + (1 << d); } else { returnask(t[p].trans[v], d - 1, x); } } }
int ans;
namespace SAM { int NodeCount = 1, Last = 1; structnode { int trans[26]; int link, maxl; } t[SIZE];
intcreate(){ int p = ++ NodeCount; for (int i = 0; i < 26; i ++) t[p].trans[i] = 0; t[p].link = t[p].maxl = 0; return p; }
voidinit(){ NodeCount = 0; Last = create(); }
voidextend(int c, int i){ int p = Last, np = Last = create(); t[np].maxl = t[p].maxl + 1; for (; p && t[p].trans[c] == 0; p = t[p].link) t[p].trans[c] = np;
if (!p) { t[np].link = 1; } else { int q = t[p].trans[c];
std::vector<int> son[SIZE]; voidbuild_tree(){ for (int i = 1; i <= NodeCount; i ++) { son[i].clear(); } for (int i = 2; i <= NodeCount; i ++) { son[t[i].link].push_back(i); } }
voidsolve(int u){ for (int v : son[u]) { solve(v);
if (g[u].size() < g[v].size()) { std::swap(g[u], g[v]); std::swap(root[u], root[v]); }