# LOJ 3049: 洛谷 P5284: 「十二省联考 2019」字符串问题

### 题意简述：

$n_a$ 个 A 类串，都是 $S$ 的子串，以区间的形式给出。

$n_b$ 个 B 类串，都是 $S$ 的子串，以区间的形式给出。

$m$ 个支配关系，形式为第 $i$ 个 A 类串支配第 $j$ 个 B 类串。

### 题解：

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>

typedef long long LL;
const int MN = 200005;
const int MS = 4200005;

char str[MN];
int N, Sig, rk[MN], SA[MN], SA2[MN], buk[MN], tmp[MN];
int Height[MN];
inline void getHeight() {
for (int i = 1, k = 0; i <= N; ++i) {
if (rk[i] == 1) { Height[rk[i]] = k = 0; continue; }
if (k) --k;
int j = SA[rk[i] - 1];
while (i + k <= N && j + k <= N && str[i + k] == str[j + k]) ++k;
Height[rk[i]] = k;
}
}
inline void RSort() {
for (int i = 1; i <= Sig; ++i) buk[i] = 0;
for (int i = 1; i <= N; ++i) ++buk[rk[i]];
for (int i = 1; i <= Sig; ++i) buk[i] += buk[i - 1];
for (int i = N; i >= 1; --i) SA[buk[rk[SA2[i]]]--] = SA2[i];
}
inline void getSA(char *str) {
Sig = 127, rk[N + 1] = 0;
for (int i = 1; i <= N; ++i) rk[i] = str[i], SA2[i] = i;
RSort();
for (int j = 1; j <= N; j <<= 1) {
int p = 0;
for (int i = N - j + 1; i <= N; ++i) SA2[++p] = i;
for (int i = 1; i <= N; ++i) if (SA[i] > j) SA2[++p] = SA[i] - j;
RSort();
tmp[SA[1]] = p = 1;
for (int i = 2; i <= N; ++i) {
int lst = SA[i - 1], now = SA[i];
if (rk[lst] != rk[now] || rk[lst + j] != rk[now + j]) ++p;
tmp[SA[i]] = p;
}
for (int i = 1; i <= N; ++i) rk[i] = tmp[i];
if ((Sig = p) == N) break;
}
getHeight();
}

int Lg[MN];
inline void Log(int N) {
Lg[0] = -1;
for (int i = 1; i <= N; ++i) Lg[i] = Lg[i >> 1] + 1;
}
int ST[MN][18];
inline void InitST() {
for (int i = 2; i <= N; ++i) ST[i][0] = Height[i];
for (int j = 1; j <= Lg[N - 1]; ++j) {
for (int i = 1; i <= 1 << j; ++i) ST[i][j] = 0;
for (int i = 1 << j | 1; i <= N; ++i)
ST[i][j] = std::min(ST[i - (1 << (j - 1))][j - 1], ST[i][j - 1]);
}
}

int NA, la[MN], ra[MN];
int NB, lb[MN], rb[MN];
struct sub {
int lb, len, typ, id;
sub() {}
sub(int lb, int len, int typ, int id) : lb(lb), len(len), typ(typ), id(id) {}
inline friend bool operator <(sub i, sub j) {
return i.len == j.len ? i.typ < j.typ : i.len > j.len;
}
} substrs[MN * 2];

int d[MS];
std::vector<int> G[MS];
inline void addEdge(int x, int y) { ++d[y]; G[x].push_back(y); }

int rt[MN], lc[MS], rc[MS], wgh[MS], cnt;
void Mdf(int &rt, int l, int r, int p, int x) {
lc[++cnt] = lc[rt], rc[cnt] = rc[rt];
if (rt) addEdge(cnt, rt);
wgh[rt = cnt] = 0;
if (l == r) { addEdge(rt, x); return ; }
int mid = (l + r) >> 1;
if (p <= mid) Mdf(lc[rt], l, mid, p, x), addEdge(rt, lc[rt]);
else Mdf(rc[rt], mid + 1, r, p, x), addEdge(rt, rc[rt]);
}
void Edg(int rt, int l, int r, int a, int b, int x) {
if (!rt || r < a || b < l) return ;
if (a <= l && r <= b) { addEdge(x, rt); return ; }
int mid = (l + r) >> 1;
Edg(lc[rt], l, mid, a, b, x);
Edg(rc[rt], mid + 1, r, a, b, x);
}

int que[MS], l, r;
LL f[MS];

int main() {
int T; scanf("%d", &T);
Log(200000);
while (T--) {
scanf("%s", str + 1);
N = strlen(str + 1);
getSA(str);
InitST();
scanf("%d", &NA);
for (int i = 1; i <= NA; ++i)
scanf("%d%d", &la[i], &ra[i]),
substrs[i] = sub(rk[la[i]], ra[i] - la[i] + 1, 0, i);
scanf("%d", &NB);
for (int i = 1; i <= NB; ++i)
scanf("%d%d", &lb[i], &rb[i]),
substrs[NA + i] = sub(rk[lb[i]], rb[i] - lb[i] + 1, 1, i);
std::sort(substrs + 1, substrs + NA + NB + 1);
cnt = NA + NB;
for (int i = 1; i <= NA; ++i) wgh[i] = ra[i] - la[i] + 1;
for (int i = 1; i <= NB; ++i) wgh[NA + i] = 0;
for (int i = 1, gen = 0; i <= NA + NB; ++i) {
sub p = substrs[i];
if (!p.typ) ++gen, Mdf(rt[gen] = rt[gen - 1], 1, N, p.lb, p.id);
else {
int Lb = p.lb, Rb = p.lb;
for (int j = Lg[p.lb - 1]; ~j; --j)
if (ST[Lb][j] >= p.len) Lb -= 1 << j;
for (int j = Lg[N - p.lb]; ~j; --j)
if (Rb + (1 << j) <= N && ST[Rb + (1 << j)][j] >= p.len) Rb += 1 << j;
Edg(rt[gen], 1, N, Lb, Rb, NA + p.id);
}
}
int M; scanf("%d", &M);
for (int i, j; M--; ) {
scanf("%d%d", &i, &j);
addEdge(i, NA + j);
}
LL Ans = 0;
l = 1, r = 0;
for (int i = 1; i <= cnt; ++i) {
f[i] = wgh[i];
if (!d[i]) que[++r] = i;
}
while (l <= r) {
int u = que[l++];
Ans = std::max(Ans, f[u]);
for (auto v : G[u]) {
f[v] = std::max(f[v], f[u] + wgh[v]);
if (!--d[v]) que[++r] = v;
}
}
if (r != cnt) puts("-1");
else printf("%lld\n", Ans);
for (int i = 1; i <= cnt; ++i) d[i] = 0, G[i].clear();
}
return 0;
}


posted @ 2019-04-11 23:27  粉兔  阅读(...)  评论(...编辑  收藏