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; }
相关文章推荐
- glPushAttrib保存属性组 改变属性 glPopAttrib恢复属性组
- linux 终端输出颜色
- 数据库中间件OneProxy简明使用手册
- 调用远程主机上的RMI服务时抛出java.rmi.ConnectException: Connection refused to host: 127.0.0.1异常原因及解决方案
- Ping的工作过程及单向Ping通的原因
- js 保留两位小数,不要四舍五入
- JavaSE入门学习43:文件传输基础之I/O流(二)
- mysql 将时间戳直接转换成日期时间
- Activity中的onSaveInstanceState()解析
- C与C++之间的调用
- 两次分页显示内容——先少后多显示
- [置顶] iOS 远程推送 根据后台推送内容的不同跳转指定页面
- linux screen 命令详解
- linux套接字编程之多进程多线程练习
- 你真的会用Retrofit2吗?Retrofit2完全教程
- 数据库_MySQL_复杂SQL的书写顺序与执行过程
- 简谈快速排序
- 操作系统知识(5)--Linux vi/vim
- Intent使用Parcelable传递对象
- Solr源码解析之一 -- 查询解析器QueryParser