mark。
cf666e,cf700e
进度1/2
码量大的吐血,思路顺了翘起来很爽,一卡直接被巨量的代码搞得瞬间暴死。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int maxn = 6e5 + 5;
int n, q;
string s, pp;
pii cmp(pii a, pii b) {
if (a.second == b.second) {
if (a.first < b.first) {
return a;
}
return b;
}
if (a.second < b.second) {
return b;
}
return a;
}
struct Sam {
int next[maxn << 1][26];
int link[maxn << 1], step[maxn << 1];
int endpos[maxn << 1], id[maxn];
int a[maxn], b[maxn << 1];
int sz, last, root;
int ls[maxn * 50], rs[maxn * 50], tot;
pii tree[maxn * 50];
int rmq[maxn << 1][21];
void update(int &i, int l, int r, int pos) {
if (!i) {
i = ++tot;
}
if (l == r) {
tree[i].first = l;
++tree[i].second;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) {
update(ls[i], l, mid, pos);
} else {
update(rs[i], mid + 1, r, pos);
}
tree[i] = cmp(tree[ls[i]], tree[rs[i]]);
}
int merge(int x, int y, int l, int r) {
if (!x || !y) {
return x + y;
}
int z = ++tot, mid = (l + r) >> 1;
// tree[z] = cmp(tree[x], tree[y]);
if (l == r) {
tree[z] = {l, tree[x].second + tree[y].second};
return z;
}
ls[z] = merge(ls[x], ls[y], l, mid);
rs[z] = merge(rs[x], rs[y], mid + 1, r);
tree[z] = cmp(tree[ls[z]], tree[rs[z]]);
return z;
}
pii query(int i, int l, int r, int L, int R) {
if (l >= L && r <= R) {
return tree[i];
}
int mid = (l + r) >> 1;
pii ans = {0, 0};
if (L <= mid) {
ans = cmp(ans, query(ls[i], l, mid, L, R));
}
if (R > mid) {
ans = cmp(ans, query(rs[i], mid + 1, r, L, R));
}
return ans;
}
void init() {
//如多次建立自动机,加入memset操作
root = sz = last = 1;
}
void add(int c) {
if (next[last][c] && step[last] + 1 == step[next[last][c]]) {
last = next[last][c];
return;
}
int p = last;
int np = ++sz;
last = np;
step[np] = step[p] + 1;
while (!next[p][c] && p) {
next[p][c] = np;
p = link[p];
}
if (p == 0) {
link[np] = root;
} else {
int q = next[p][c];
if (step[p] + 1 == step[q]) {
link[np] = q;
} else {
int nq = ++sz;
memcpy(next[nq], next[q], sizeof(next[q]));
step[nq] = step[p] + 1;
link[nq] = link[q];
link[q] = link[np] = nq;
while (next[p][c] == q && p) {
next[p][c] = nq;
p = link[p];
}
}
}
}
void build() {
init();
for (int i = 0; i < pp.length(); ++i) {
add(pp[i] - 'a');
id[i] = last;
}
for (int i = 1; i <= n; ++i) {
cin >> s;
last = root;
for (int j = 0; j < s.length(); ++j) {
add(s[j] - 'a');
update(endpos[last], 1, n, i);
}
}
for (int i = root; i <= sz; ++i) {
rmq[i][0] = link[i];
}
for (int j = 1; j <= 20; ++j) {
for (int i = root; i <= sz; ++i) {
rmq[i][j] = rmq[rmq[i][j - 1]][j - 1];
}
}
for (int i = 1; i <= sz; i++) {
a[step[i]]++;
}
for (int i = 1; i <= sz; i++) {
a[i] += a[i - 1];
}
for (int i = 1; i <= sz; i++) {
b[a[step[i]]--] = i;
}
for (int i = sz; i > root; --i) {
int e = b[i];
endpos[link[e]] = merge(endpos[link[e]], endpos[e], 1, n);
}
}
void solve(int l, int r, int pl, int pr) {
int p = id[pr];
for (int i = 20; ~i; --i) {
if (step[rmq[p][i]] >= pr - pl + 1) {
p = rmq[p][i];
}
}
pii ans = query(endpos[p], 1, n, l, r);
if (ans.first == 0) {
cout << l << " " << 0 << '\n';
return;
}
cout << ans.first << ' ' << ans.second << '\n';
}
} sam;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> pp >> n;
sam.build();
cin >> q;
int l, r, pl, pr;
while (q--) {
cin >> l >> r >> pl >> pr;
sam.solve(l, r, pl - 1, pr - 1);
}
return 0;
}
mark2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
int n;
string s;
struct Sam {
int next[maxn << 1][26];
int link[maxn << 1], step[maxn << 1];
int endpos[maxn << 1], pos[maxn << 1];
int a[maxn], b[maxn << 1];
int subseq[maxn << 1], dp[maxn << 1];
int sz, last, root;
int ls[maxn * 50], rs[maxn * 50], tot;
void update(int &i, int l, int r, int pos) {
if (!i) {
i = ++tot;
}
if (l == r) {
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) {
update(ls[i], l, mid, pos);
} else {
update(rs[i], mid + 1, r, pos);
}
}
int merge(int x, int y) {
if (!x || !y) {
return x + y;
}
int z = ++tot;
ls[z] = merge(ls[x], ls[y]);
rs[z] = merge(rs[x], rs[y]);
return z;
}
int query(int i, int l, int r, int L, int R) {
if (!i) {
return 0;
}
if (l >= L && r <= R) {
return 1;
}
int mid = (l + r) >> 1;
int ans = 0;
if (L <= mid) {
ans |= query(ls[i], l, mid, L, R);
}
if (R > mid) {
ans |= query(rs[i], mid + 1, r, L, R);
}
return ans;
}
void init() {
//如多次建立自动机,加入memset操作
root = sz = last = 1;
}
void add(int c, int id) {
int p = last;
int np = ++sz;
last = np;
pos[np] = id;
update(endpos[np], 1, n, id);
step[np] = step[p] + 1;
while (!next[p][c] && p) {
next[p][c] = np;
p = link[p];
}
if (p == 0) {
link[np] = root;
} else {
int q = next[p][c];
if (step[p] + 1 == step[q]) {
link[np] = q;
} else {
int nq = ++sz;
memcpy(next[nq], next[q], sizeof(next[q]));
step[nq] = step[p] + 1;
link[nq] = link[q];
pos[nq] = pos[q];
link[q] = link[np] = nq;
while (next[p][c] == q && p) {
next[p][c] = nq;
p = link[p];
}
}
}
}
void build() {
init();
for (int i = 0; i < s.length(); i++) {
add(s[i] - 'a', i + 1);
}
for (int i = 1; i <= sz; i++) {
a[step[i]]++;
}
for (int i = 1; i <= step[last]; i++) {
a[i] += a[i - 1];
}
for (int i = 1; i <= sz; i++) {
b[a[step[i]]--] = i;
}
for (int i = sz; i >= root; --i) {
int e = b[i];
endpos[link[e]] = merge(endpos[link[e]], endpos[e]);
}
}
void solve() {
int ans = 1;
for (int i = root; i <= sz; ++i) {
int e = b[i];
if (link[e] == root) {
dp[e] = 1, subseq[e] = e;
} else if (query(endpos[subseq[link[e]]], 1, n, pos[e] - step[e] + step[subseq[link[e]]], pos[e] - 1)) {
dp[e] = dp[link[e]] + 1, subseq[e] = e;
} else {
dp[e] = dp[link[e]], subseq[e] = subseq[link[e]];
}
ans = max(ans, dp[e]);
}
cout << ans;
}
} sam;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> s;
sam.build();
sam.solve();
return 0;
}