# Sol

$f[i]$ 表示以 $i$ 这个子串结尾的最大的答案

$right$ 集合和查询直接线段树合并+查询即可

# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
# define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
using namespace std;
typedef long long ll;

IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}

const int maxn(4e5 + 5);

int n, tot, last, trans[26][maxn], fa[maxn], len[maxn];
int first[maxn], nxt[maxn], rt[maxn], sz[maxn * 20], cnt, ls[maxn * 20], rs[maxn * 20];
int nt[maxn], fp[maxn], f[maxn], pos[maxn], ans;
char s[maxn];

IL void Modify(RG int &x, RG int l, RG int r, RG int p){
if(!x) x = ++cnt;
++sz[x];
if(l == r) return;
RG int mid = (l + r) >> 1;
p <= mid ? Modify(ls[x], l, mid, p) : Modify(rs[x], mid + 1, r, p);
}

IL int Merge(RG int x, RG int y){
if(!x || !y) return x + y;
RG int z = ++cnt;
sz[z] = sz[x] + sz[y];
ls[z] = Merge(ls[x], ls[y]);
rs[z] = Merge(rs[x], rs[y]);
return z;
}

IL int Query(RG int x, RG int l, RG int r, RG int ql, RG int qr){
if(!x || l > r) return 0;
if(ql <= l && qr >= r) return sz[x];
RG int mid = (l + r) >> 1, sum = 0;
if(ql <= mid) sum = Query(ls[x], l, mid, ql, qr);
if(qr > mid) sum += Query(rs[x], mid + 1, r, ql, qr);
return sum;
}

IL void Extend(RG int c, RG int id){
RG int p = last, np = ++tot;
len[last = np] = len[p] + 1, pos[np] = id;
while(p && !trans[c][p]) trans[c][p] = np, p = fa[p];
if(!p) fa[np] = 1;
else{
RG int q = trans[c][p];
if(len[q] == len[p] + 1) fa[np] = q;
else{
RG int nq = ++tot;
fa[nq] = fa[q], len[nq] = len[p] + 1;
for(RG int i = 0; i < 26; ++i) trans[i][nq] = trans[i][q];
fa[np] = fa[q] = nq;
while(p && trans[c][p] == q) trans[c][p] = nq, p = fa[p];
}
}
Modify(rt[last], 1, n, id);
}

IL void Dfs1(RG int u){
for(RG int v = first[u]; v; v = nxt[v]){
Dfs1(v);
rt[u] = Merge(rt[u], rt[v]);
if(!pos[u]) pos[u] = pos[v];
}
}

IL void Dfs2(RG int u){
fp[u] = 1;
if(u != 1){
if(fa[u] == 1) f[u] = 1;
else{
RG int p = fp[fa[u]]; f[u] = f[fa[u]];
while(p != u && Query(rt[p], 1, n, pos[u] - len[u] + len[p], pos[u] - 1)){
f[u] = max(f[u], f[fp[u] = p] + 1);
p = nt[p];
}
}
}
for(RG int v = first[u]; v; v = nxt[v]) nt[u] = v, Dfs2(v);
}

int main(){
n = Input(), scanf(" %s", s + 1), tot = last = 1;
for(RG int i = 1; i <= n; ++i) Extend(s[i] - 'a', i);
for(RG int i = 1; i <= tot; ++i) nxt[i] = first[fa[i]], first[fa[i]] = i;
Dfs1(1), Dfs2(1);
for(RG int i = 1; i <= tot; ++i) ans = max(ans, f[i]);
printf("%d\n", ans);
return 0;
}

posted @ 2018-06-12 15:37  Cyhlnj  阅读(...)  评论(...编辑  收藏