Loj2059. 「TJOI / HEOI2016」字符串
来源:互联网 发布:les聊天软件 编辑:程序博客网 时间:2024/06/05 19:51
Loj2059. 「TJOI / HEOI2016」字符串
题意:给定一个串,问
考虑将串反转,则变成了最长公共后缀问题。
二分答案
考虑用线段树合并维护
#include <bits/stdc++.h>using namespace std;const int MAXN = 200005;int lc[MAXN*50], rc[MAXN*50], top = 0;int build(int &nd, int pos, int L, int R){ nd = ++top; if (L == R) return nd; else { int mid = (L+R)>>1; if (pos <= mid) return build(lc[nd], pos, L, mid); else return build(rc[nd], pos, mid+1, R); }}int merge(int a, int b){ if (a == 0 || b == 0) return a+b; int c = ++top; lc[c] = merge(lc[a], lc[b]), rc[c] = merge(rc[a], rc[b]); return c;}bool query(int nd, int opl, int opr, int L, int R){ if (!nd) return 0; if (opl == L && opr == R) return 1; else { int mid = (L+R)>>1; if (opr <= mid) return query(lc[nd], opl, opr, L, mid); else if (opl > mid) return query(rc[nd], opl, opr, mid+1, R); else return query(lc[nd], opl, mid, L, mid)||query(rc[nd], mid+1, opr, mid+1, R); }}int chl[MAXN*2][26], fa[MAXN*2][21], maxl[MAXN*2], sam_top = 1, root = 1, last = 1;int rt[MAXN*2], fin[MAXN*2];int n, m;char str[MAXN*2];void push(int x, int id){ int p = last, np = ++sam_top; maxl[np] = maxl[p]+1, build(rt[np], id, 1, n); while (p && !chl[p][x]) chl[p][x] = np, p = fa[p][0]; if (!p) fa[np][0] = root; else { int q = chl[p][x]; if (maxl[q] == maxl[p]+1) fa[np][0] = q; else { int nq = ++sam_top; maxl[nq] = maxl[p]+1; memcpy(chl[nq], chl[q], sizeof chl[q]); fa[nq][0] = fa[q][0], fa[q][0] = fa[np][0] = nq; while (p && chl[p][x] == q) chl[p][x] = nq, p = fa[p][0]; } } fin[id] = last = np;}struct node { int to, next;} edge[MAXN*2];int head[MAXN*2], tree_top = 0;void push_tree(int i, int j){ edge[++tree_top] = (node) {j, head[i]}, head[i] = tree_top; }void dfs(int nd){ // for (int i = 1; i <= tab; i++) cerr << " "; // cerr << nd << endl; for (int i = head[nd]; i; i = edge[i].next) { int to = edge[i].to; dfs(to), rt[nd] = merge(rt[nd], rt[to]); }}void init(){ scanf("%d%d", &n, &m); scanf("%s", str+1); reverse(str+1, str+n+1); for (int i = 1; i <= n; i++) push(str[i]-'a', i); for (int j = 1; j < 20; j++) for (int i = 1; i <= sam_top; i++) fa[i][j] = fa[fa[i][j-1]][j-1]; for (int i = 2; i <= sam_top; i++) { push_tree(fa[i][0], i); // cerr << i << "," << fa[i][0] << endl; } dfs(root);}bool judge(int pos, int mid, int a, int b){ for (int i = 19; i >= 0; i--) if (maxl[fa[pos][i]] >= mid) pos = fa[pos][i]; /*cerr << pos << " " << rt[pos] << " " << a-mid+1 << " " << b << endl; for (int i = 1; i <= 5; i++) cerr << query(rt[pos], i, i, 1, n) << " "; cerr << endl;*/ return query(rt[pos], a+mid-1, b, 1, n);}int main(){ init(); for (int i = 1; i <= m; i++) { int a, b, c, d; scanf("%d%d%d%d", &b, &a, &d, &c); a = n-a+1, b = n-b+1, c = n-c+1, d = n-d+1; int pos = fin[d]; int L = 1, R = min(b-a+1, d-c+1), mid; while (L <= R) { mid = (L+R)>>1; if (judge(pos, mid, a, b)) L = mid+1; else R = mid-1; } printf("%d\n", L-1); } return 0;}
阅读全文
0 0
- Loj2059. 「TJOI / HEOI2016」字符串
- [bzoj4556][TJOI&&HEOI2016]字符串
- [TJOI&HEOI2016]str/[JZOJ4614]字符串
- 【TJOI&HEOI2016】bzoj4556 字符串【解法一】
- 【TJOI&HEOI2016】bzoj4556 字符串【解法二】
- [bzoj4551][TJOI&HEOI2016]树
- [bzoj4552][TJOI&HEOI2016]排序
- [bzoj4553][TJOI&HEOI2016]序列
- [bzoj4552][TJOI&&HEOI2016]排序
- [TJOI&HEOI2016]排序
- [bzoj4555][TJOI&HEOI2016]求和
- 【bzoj4555】[TJOI&HEOI2016]求和
- [TJOI&HEOI2016]seq/[JZOJ4606]序列
- [BZOJ4551][JZOJ4604]【TJOI&HEOI2016】D1T1 树
- [BZOJ4552][JZOJ4605]【TJOI&HEOI2016】D1T2 排序
- [BZOJ4554][JZOJ4612] 【TJOI&HEOI2016】D2T1 游戏
- BZOJ4556: [Tjoi2016&Heoi2016]字符串
- 4556: [Tjoi2016&Heoi2016]字符串
- 初窥javaScrit权威指南,第六章对象(2)
- VS中如何设置自己的快捷代码段
- 深拷贝deepcopy与浅拷贝copy
- Docker 最常用的监控方案
- html
- Loj2059. 「TJOI / HEOI2016」字符串
- python合并多个csv文件
- proc文件系统创建实例二(引出 seq file 文件系统的创建过程,结构化信息显示)
- animation布局,style
- c++回文日期【NOIP2016普及组】解题报告
- JQuery
- 电影样题的数据清洗
- struts2的简单使用
- CSS3圆角