CF1098F Ж-function [后缀自动机+扫描线]
这题好仙啊,不会。后面看懂了再来填坑吧。
// by Isaunoya
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 4e5 + 58;
using ll = long long;
struct smt {
int n, size, rt;
int ls[maxn << 1], rs[maxn << 1];
ll tag[maxn << 1];
ll cnt[maxn << 1], sum[maxn << 1];
void init(int sz, int *tmp) {
size = rt = 0, n = sz, bld(rt, 1, n, tmp);
}
void up(int p) {
sum[p] = sum[ls[p]] + sum[rs[p]];
}
void bld(int &p, int l, int r, int *tmp) {
p = ++ size;
if(l == r) {
cnt[p] = tmp[l];
return;
}
int mid = l + r >> 1;
bld(ls[p], l, mid, tmp);
bld(rs[p], mid + 1, r, tmp);
cnt[p] = cnt[ls[p]] + cnt[rs[p]];
}
void down(int p) {
if(tag[p]) {
tag[ls[p]] += tag[p], sum[ls[p]] += tag[p] * cnt[ls[p]];
tag[rs[p]] += tag[p], sum[rs[p]] += tag[p] * cnt[rs[p]];
tag[p] = 0;
}
}
void mdf(int p, int ql, int qr, int l, int r, int v) {
if(ql <= l && r <= qr) {
tag[p] += v, sum[p] += v * cnt[p];
return;
}
down(p);
int mid = l + r >> 1;
if(ql <= mid) mdf(ls[p], ql, qr, l, mid, v);
if(qr > mid) mdf(rs[p], ql, qr, mid + 1, r, v);
up(p);
}
void mdf(int ql, int qr, int v) {
mdf(rt, ql, qr, 1, n, v);
}
ll qry(int p, int ql, int qr, int l, int r) {
if(ql <= l && r <= qr) {
return sum[p];
}
down(p);
int mid = l + r >> 1;
ll ans = 0;
if(ql <= mid) ans += qry(ls[p], ql, qr, l, mid);
if(qr > mid) ans += qry(rs[p], ql, qr, mid + 1, r);
return ans;
}
int qry(int ql, int qr) {
return qry(rt, ql, qr, 1, n);
}
ll qry(int p, int x, int l, int r) {
if(l == r) {
return tag[p];
}
down(p);
int mid = l + r >> 1;
if(x <= mid) return qry(ls[p], x, l, mid);
else return qry(rs[p], x, mid + 1, r);
}
ll qry(int x) { return qry(rt, x, 1, n); }
} smt;
struct BIT {
int n;
vector <ll> c;
void init(int _n) {
n = _n + 1;
c.resize(n + 1);
}
int low(int x) {
return x & -x;
}
void u(int x, int y) {
for(; x <= n; x += low(x)) c[x] += y;
}
ll q(int x) {
ll ans = 0;
for(; x; x ^= low(x)) ans += c[x];
return ans;
}
ll qry(int x) { return q(x); }
ll qry(int l, int r) {
if(l > r)
return 0;
return q(r) - q(l - 1);
}
} al[2], pt[2];
int pos[maxn], rev[maxn];
struct suffixautomaton {
int ch[maxn][26], fa[maxn], len[maxn];
int las, cnt;
suffixautomaton() { las = cnt = 1; }
void ins(int c, int id) {
int p = las, np = las = ++cnt;
pos[np] = id;
len[np] = len[p] + 1;
for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
if(!p) {
fa[np] = 1;
} else {
int q = ch[p][c];
if(len[q] == len[p] + 1) {
fa[np] = q;
} else {
int nq = ++cnt;
len[nq] = len[p] + 1;
fa[nq] = fa[q], fa[q] = fa[np] = nq;
memcpy(ch[nq], ch[q], sizeof(ch[q]));
for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
}
}
}
} sam;
int n, t, len;
char s[maxn];
int dep[maxn], f[maxn][22];
vector <int> g[maxn];
int ql[maxn], qr[maxn], from[maxn];
int sz[maxn], fa[maxn], son[maxn];
void dfs(int u) {
sz[u] = 1;
for(int v: g[u]) {
if(v ^ fa[u]) {
fa[v] = u, dfs(v), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
}
int top[maxn], dfn[maxn];
//dfo[maxn];
int idx = 0;
void dfs(int u, int t) {
top[u] = t, dfn[u] = ++ idx;
if(son[u]) dfs(son[u], t);
for(int v: g[u])
if(!top[v]) dfs(v, v);
// dfo[u] = idx;
}
ll ans[maxn];
void Scanninglinefir() {
static int tmp[maxn];
for(int i = 1 ; i <= n ; i ++) {
tmp[dfn[i]] = dep[i] - dep[fa[i]];
}
smt.init(n, tmp);
static vector <pair<pair<int, int>, int>> q[maxn];
for(int i = 1 ; i <= t ; i ++) {
q[ql[i]].push_back(make_pair(make_pair(from[i], qr[i] - ql[i] + 1), i));
}
for(int i = 1 ; i <= len ; i ++) {
auto query = [&](pair<int, int> x) {
ll ans = 1ll * (x.second - dep[fa[x.first]]) * smt.qry(dfn[x.first]);
int pos = fa[x.first];
while(pos) {
ans += smt.qry(dfn[top[pos]], dfn[pos]), pos = fa[top[pos]];
}
return ans;
};
for(auto x : q[i]) {
ans[x.second] -= query(x.first);
}
int pos = rev[i];
while(pos) {
smt.mdf(dfn[top[pos]], dfn[pos], 1), pos = fa[top[pos]];
}
}
}
void Scanninglinesec() {
static vector <pair<int, int>> mdf[maxn];
static vector <pair<pair<int, int>, int>> qry[maxn];
for(int i = 1 ; i <= len ; i ++) {
int pos = rev[i];
while(pos) {
mdf[top[pos]].emplace_back(dep[pos], i), pos = fa[top[pos]];
}
}
for(int i = 1 ; i <= t ; i ++) {
int pos = from[i];
while(pos) {
if(pos == from[i]) {
qry[top[pos]].emplace_back(make_pair(qr[i] - ql[i] + 1, qr[i] + 1), i);
} else {
qry[top[pos]].emplace_back(make_pair(dep[pos], qr[i] + 1), i);
}
pos = fa[top[pos]];
}
}
al[0].init(len * 2 + 2), al[1].init(len * 2 + 2);
pt[0].init(len * 2 + 2), pt[1].init(len * 2 + 2);
for(int i = 1 ; i <= n ; i ++) {
if(top[i] != i) { continue; }
int st = dep[fa[i]] + 1;
sort(mdf[i].begin(), mdf[i].end()), reverse(mdf[i].begin(), mdf[i].end());
sort(qry[i].begin(), qry[i].end()), reverse(qry[i].begin(), qry[i].end());
vector <pair<int, int>> bak = mdf[i];
for(auto x: bak) {
al[0].u(x.second, x.second), al[1].u(x.second, 1);
}
while(!mdf[i].empty() || !qry[i].empty()) {
if(mdf[i].empty() || (!qry[i].empty() && qry[i].back().first.first <= mdf[i].back().first)) {
pair <int, int> x = qry[i].back().first;
int pos = qry[i].back().second;
ans[pos] += 1ll * pt[1].qry(x.second) * x.second + pt[0].qry(x.second);
int tmp = x.second - x.first;
if(tmp >= 1) {
ans[pos] += al[1].qry(1, tmp) * (x.first - st + 1);
}
tmp = max(tmp, 0ll);
ans[pos] += 1ll * al[1].qry(tmp + 1, x.second - st) * (x.second - st + 1) - al[0].qry(tmp + 1, x.second - st);
qry[i].pop_back();
} else {
pair <int, int> x = mdf[i].back();
al[0].u(x.second, -x.second), al[1].u(x.second, -1);
pt[0].u(st + x.second, -(st + x.second - 1));
pt[0].u(x.first + x.second + 1, st + x.second - 1 + x.first - st + 1);
pt[1].u(st + x.second, 1), pt[1].u(x.first + x.second + 1, -1);
mdf[i].pop_back();
}
}
for(auto x: bak) {
pt[0].u(st + x.second, st + x.second - 1);
pt[0].u(x.first + x.second + 1, -(st + x.second - 1 + x.first - st + 1));
pt[1].u(st + x.second, -1), pt[1].u(x.first + x.second + 1, 1);
}
}
}
signed main() {
#ifdef LOCAL
freopen("testdata.in", "r", stdin);
#endif
scanf("%s", s + 1);
len = strlen(s + 1);
for(int i = len ; i ; i --) {
sam.ins(s[i] - 'a', i);
}
n = sam.cnt;
for(int i = 1 ; i <= n ; i ++) {
dep[i] = sam.len[i];
if(pos[i]) rev[pos[i]] = i;
}
for(int i = 2 ; i <= n ; i ++) {
g[sam.fa[i]].push_back(i);
}
dfs(1), dfs(1, 1);
scanf("%lld", &t);
for(int i = 1 ; i <= t ; i ++) {
int l, r; scanf("%lld %lld", &l, &r);
ql[i] = l, qr[i] = r;
}
for(int i = 1 ; i <= n ; i ++) {
f[i][0] = sam.fa[i];
}
for(int j = 1 ; j <= 20 ; j ++)
for(int i = 1 ; i <= n ; i ++) f[i][j] = f[f[i][j - 1]][j - 1];
for(int i = 1 ; i <= t ; i ++) {
int l = ql[i], r = qr[i], goal = r - l + 1, p = rev[l];
for(int j = 20; ~j; -- j) if(f[p][j] && dep[f[p][j]] >= goal) p = f[p][j];
from[i] = p;
}
Scanninglinefir(), Scanninglinesec();
for(int i = 1 ; i <= t ; i ++) printf("%lld\n", ans[i]);
return 0;
}