Codeforces 666E Forensic Examination (sam+线段树合并)

来源:互联网 发布:太阳能电池计算软件 编辑:程序博客网 时间:2024/06/03 15:19
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <map>#include <set>#include <algorithm>#include <ctime>#include <functional>#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;#define eps 1e-10#define N 200020#define B 20#define M 3000020#define inf 0x3f3f3f3f#define LL long long#define pii pair<int, int>#define MP make_pair#define fi first#define se second#define mod 1000000007#define md (ll + rr >> 1)struct suff_auto {int ch[N][27], val[N], par[N], id[N];int tot, lst;int creat(int v) {int k = ++tot;memset(ch[k], 0, sizeof ch[k]);val[k] = v;par[k] = 0;id[k] = -1;return k;}void init() {tot = 0;lst = creat(0);}void extend(int c, int _id) {int p = lst;int np = creat(val[p] + 1);id[np] = _id;while(p && ch[p][c] == 0) ch[p][c] = np, p = par[p];if(!p) par[np] = 1;else {int q = ch[p][c];if(val[q] == val[p] + 1) par[np] = q;else {int nq = creat(val[p] + 1);memcpy(ch[nq], ch[q], sizeof ch[q]);par[nq] = par[q];par[q] = par[np] = nq;while(p && ch[p][c] == q) ch[p][c] = nq, p = par[p];}}lst = np;}}s_auto;struct seg_t {#define TC (800020 * 40)#define md (ll + rr >> 1)int ch[TC][2], mx[TC], id[TC];int tot;void push_up(int k) {if(mx[ch[k][0]] >= mx[ch[k][1]]) mx[k] = mx[ch[k][0]], id[k] = id[ch[k][0]];else mx[k] = mx[ch[k][1]], id[k] = id[ch[k][1]];}int update(int i, int x, int v, int ll, int rr) {int k = ++tot;ch[k][0] = ch[i][0];ch[k][1] = ch[i][1];mx[k] = v;id[k] = x;if(ll == rr) return k;if(x <= md) ch[k][0] = update(ch[i][0], x, v, ll, md);else ch[k][1] = update(ch[i][1], x, v, md + 1, rr);push_up(k);return k;}int merge(int u, int v, int ll, int rr) {if(!u) return v;if(!v) return u;int k = ++tot;ch[k][0] = ch[k][1] = 0;mx[k] = mx[u] + mx[v];id[k] = ll;if(ll == rr) return k;ch[k][0] = merge(ch[u][0], ch[v][0], ll, md);ch[k][1] = merge(ch[u][1], ch[v][1], md + 1, rr);push_up(k);return k;}pair<int, int> query(int i, int l, int r, int ll, int rr) {if(i == 0) return make_pair(0, l);if(ll == l && rr == r) return make_pair(mx[i], id[i]);if(r <= md) return query(ch[i][0], l, r, ll, md);if(l > md) return query(ch[i][1], l, r, md + 1, rr);pair<int, int> x = query(ch[i][0], l, md, ll, md);pair<int, int> y = query(ch[i][1], md + 1, r, md + 1, rr);if(x.first >= y.first) return x;return y;}}sgt;int fst[N], nxt[M], vv[M], e;int val[N];int rt[N], fa[22][N], pos[N * 10], match_len[N * 10];char s[N * 10], ss[N];int n;void init() {memset(fst, -1, sizeof fst);e = 0;}void add(int u, int v) {vv[e] = v, nxt[e] = fst[u], fst[u] = e++;}void dfs(int u, int p) {fa[0][u] = p;rt[u] = 0;if(s_auto.id[u] != -1) rt[u] = sgt.update(rt[u], s_auto.id[u], 1, 1, n);for(int i = fst[u]; ~i; i = nxt[i]) {int v = vv[i];dfs(v, u);rt[u] = sgt.merge(rt[u], rt[v], 1, n);}}void fa_init() {for(int k = 0; k < 21; ++k) {for(int i = 1; i <= s_auto.tot; ++i) fa[k + 1][i] = fa[k][fa[k][i]];}}int get_pos(int u, int l) {for(int k = 20; k >= 0; --k) {int p = fa[k][u];if(p == 0) continue;if(val[p] >= l) u = p;}return u;}int main() {scanf("%s", s + 1);scanf("%d", &n);s_auto.init();for(int i = 1; i <= n; ++i) {scanf("%s", ss);for(int j = 0; ss[j]; ++j) {int c = ss[j] - 'a';s_auto.extend(c, i);}s_auto.extend(26, -1);}init();for(int i = 2; i <= s_auto.tot; ++i) {add(s_auto.par[i], i);}for(int i = 1; i <= s_auto.tot; ++i) {val[i] = s_auto.val[i];}dfs(1, 0);fa_init();int t = 1, len = 0;for(int i = 1; s[i]; ++i) {int c = s[i] - 'a';if(s_auto.ch[t][c]) t = s_auto.ch[t][c], len++;else {while(t && s_auto.ch[t][c] == 0) t = s_auto.par[t];if(!t) {t = 1, len = 0;}else {len = val[t] + 1;t = s_auto.ch[t][c];}}pos[i] = t;match_len[i] = len;}int q;scanf("%d", &q);while(q--) {int l, r, pl, pr;scanf("%d%d%d%d", &pl, &pr, &l, &r);int t = r - l + 1;if(match_len[r] < t) {printf("%d 0\n", pl);continue;}int u = get_pos(pos[r], t);pair<int, int> ans = sgt.query(rt[u], pl, pr, 1, n);printf("%d %d\n", ans.second, ans.first);}return 0;}

0 0
原创粉丝点击