1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
#include <bits/stdc++.h> using namespace std; template <typename T> inline void read(T &a){ T w = 1; a = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') w = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) a = (a * 10) + (ch - '0'); a *= w; } template <typename T> inline void ckmax(T &a, T b){a = a > b ? a : b;} template <typename T> inline void ckmin(T &a, T b){a = a < b ? a : b;} #define fi first #define se second #define pb push_back #define mp make_pair #define mii map<int, int> #define pii pair<int, int> #define vi vector<int> #define si set<int> #define ins insert #define era erase #define Debug(x) cout << #x << " = " << x << endl #define For(i,l,r) for (int i = l; i <= r; ++i) #define foR(i,l,r) for (int i = l; i >= r; --i) const int N = 2e5 + 10; const int M = 1e7 + 10; struct state { int len, nxt[26], link, pos; } st[N << 1]; int siz = 1, las = 1; int id[N]; inline void extend (int c, int i) { int cur = ++siz, p = las; las = cur; id[i] = siz; st[cur].len = st[p].len + 1; st[cur].pos = i; while (p && !st[p].nxt[c]) st[p].nxt[c] = cur, p = st[p].link; if (p == 0) st[cur].link = 1; else { int q = st[p].nxt[c]; if (st[p].len + 1 == st[q].len) st[cur].link = q; else { int clone = ++siz; st[clone].len = st[p].len + 1, st[clone].link = st[q].link; st[clone].pos = st[q].pos; For (i, 0, 25) st[clone].nxt[i] = st[q].nxt[i]; st[q].link = st[cur].link = clone; while (p && st[p].nxt[c] == q) st[p].nxt[c] = clone, p = st[p].link; } } }
int rt[N << 1]; #define ls tr[x].l #define rs tr[x].r int total; struct seg { int l, r, sum; } tr[M]; inline void pushup (int x) { tr[x].sum = tr[ls].sum + tr[rs].sum; } int merge (int x, int y, int l, int r) { if (!x || !y) return x + y; if (l == r) return (tr[x].sum += tr[y].sum), x; int mid = l + r >> 1, k = ++total; tr[k].l = merge(ls, tr[y].l, l, mid), tr[k].r = merge(rs, tr[y].r, mid + 1, r); pushup(k); return k; }
void upd (int &x, int l, int r, int p) { if (!x) x = ++total; if (l == r) return (tr[x].sum++), void(); int mid = l + r >> 1; if (p <= mid) upd (ls, l, mid, p); else upd (rs, mid + 1, r, p); pushup(x); }
int que (int x, int l, int r, int ll, int rr) { if (!x) return 0; if (ll <= l && r <= rr) return tr[x].sum; int ans = 0, mid = l + r >> 1; if (ll <= mid) ans += que(ls, l, mid, ll, rr); if (rr > mid) ans += que(rs, mid + 1, r, ll, rr); return ans; }
int n; char z[N]; int you[N], se[N << 1]; inline void SORT() { For (i, 1, siz) you[st[i].len]++; For (i, 1, n) you[i] += you[i - 1]; For (i, 1, siz) se[you[st[i].len]--] = i; } int dp[N << 1]; int main() { read(n); scanf ("%s", z + 1); id[0] = 1; For (i, 1, n) extend(z[i] - 'a', i), upd(rt[id[i]], 1, n, i); SORT(); foR (i, siz, 2) rt[st[se[i]].link] = merge(rt[st[se[i]].link], rt[se[i]], 1, n);
int ans = 1; For (i, 2, siz) { int u = se[i], v = st[u].link; if (v == 1) dp[u] = 1, st[u].link = u; else { if (que(rt[st[v].link], 1, n, st[u].pos - st[u].len + st[st[v].link].len, st[u].pos - 1) ) dp[u] = dp[v] + 1, st[u].link = u; else dp[u] = dp[v], st[u].link = st[v].link; ckmax(ans, dp[u]); } } printf ("%d\n", ans); }
|