您的位置:首页 > 其它

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

2016-05-20 12:20 417 查看
#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
[27], val
, par
, id
;
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
, nxt[M], vv[M], e;
int val
;
int rt
, fa[22]
, pos[N * 10], match_len[N * 10];

char s[N * 10], ss
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: