4556: [Tjoi2016&Heoi2016]字符串
4556: [Tjoi2016&Heoi2016]字符串
分析:
首先可以二分这个长度。此时需要判断是否存在一个以b结尾的前缀,满足与[c,d]的lcp大于等于mid。
如果我们把串翻转,那么就是判断是否存在一个以b开始的后缀,这样可以建出SAM,线段树维护每个点的right集合。此时在从包含[1,b]这个状态的点沿着parent树往上跳,那么长度会减少,相应的right集合会变大,于是可以跳到第一个长度满足的点,right集合也是满足的点中最大的,看这个点中是否存在[a,b-mid+1]的位置。
SA的做法:求出height数组,二分一个长度mid,找到[c,d]的rnk设为p,从p往左往右找满足lcp长度都大于等于mid的区间[l,r],然后判断[l,r]中是否在[a,b-mid+1]中出现过。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; int ls[N * ], rs[N * ], Root[N], pos[N], ch[N][], len[N], fa[N], tmp[N], xl[N], f[N][];
int TreeIndex, Index = , Last = , n;
char s[N]; void Insert(int l,int r,int &now,int p) {
now = ++TreeIndex;
if (l == r) return ;
int mid = (l + r) >> ;
if (p <= mid) Insert(l, mid, ls[now], p);
else Insert(mid + , r, rs[now], p);
}
int query(int l,int r,int now,int L,int R) {
if (!now) return ;
if (L <= l && r <= R) return ;
int mid = (l + r) >> ;
if (L <= mid && query(l, mid, ls[now], L, R)) return ;
if (R > mid && query(mid + , r, rs[now], L, R)) return ;
return ;
}
int Merge(int x,int y) {
if (!x || !y) return x + y;
int z = ++TreeIndex;
ls[z] = Merge(ls[x], ls[y]);
rs[z] = Merge(rs[x], rs[y]);
return z;
}
void extend(int c,int i) {
int np = ++Index, p = Last; pos[i] = np; // pos[i] = np; !!!!!
len[np] = len[p] + ;
for (; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
if (!p) fa[np] = ;
else {
int q = ch[p][c];
if (len[q] == len[p] + ) fa[np] = q;
else {
int nq = ++Index;
memcpy(ch[nq], ch[q], sizeof(ch[q]));
fa[nq] = fa[q];
fa[np] = fa[q] = nq;
len[nq] = len[p] + ;
for (; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
}
}
Last = np;
Insert(, n, Root[np], i);
}
bool check(int mid,int x,int l,int r) {
for (int i = ; ~i; --i) if (len[f[x][i]] >= mid) x = f[x][i];
return query(, n, Root[x], l, r);
}
int main() {
n = read();int m = read();
scanf("%s", s + );
reverse(s + , s + n + );
for (int i = ; i <= n; ++i) extend(s[i] - 'a', i);
for (int i = ; i <= Index; ++i) tmp[len[i]] ++;
for (int i = ; i <= n; ++i) tmp[i] += tmp[i - ];
for (int i = Index; i >= ; --i) xl[tmp[len[i]]--] = i;
for (int i = Index; i > ; --i) {
int x = xl[i];
Root[fa[x]] = Merge(Root[fa[x]], Root[x]);
}
for (int i = ; i <= Index; ++i) f[i][] = fa[i];
for (int j = ; j <= ; ++j)
for (int i = ; i <= Index; ++i) f[i][j] = f[f[i][j - ]][j - ];
while (m --) {
int a = n - read() + , b = n - read() + , c = n - read() + , d = n - read() + ;
swap(a, b); swap(c, d);
int l = , r = min(d - c + , b - a + ), ans = ;
while (l <= r) {
int mid = (l + r) >> ;
if (check(mid, pos[d], a + mid - , b)) ans = mid, l = mid + ;
else r = mid - ;
}
printf("%d\n", ans);
}
return ;
}
4556: [Tjoi2016&Heoi2016]字符串的更多相关文章
- Bzoj 4556: [Tjoi2016&Heoi2016]字符串
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 177 Solved: 92[Sub ...
- BZOJ 4556: [Tjoi2016&Heoi2016]字符串(后缀数组 + 二分答案 + 主席树 + ST表 or 后缀数组 + 暴力)
题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s ...
- ●BZOJ 4556 [Tjoi2016&Heoi2016]字符串
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4556 题解: 巨恶心...但是题很好呀,可以练习好几个比较麻烦的算法~ 1).预处理 首先用 ...
- bzoj 4556 [Tjoi2016&Heoi2016]字符串——后缀数组+主席树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556 本来只要查 ht[ ] 数组上的前驱和后继就行,但有长度的限制.可以二分答案解决!然后 ...
- BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案
Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...
- Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 169 Solved: 87[Sub ...
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...
- [BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1360 Solved: 545[S ...
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1215 Solved: 484[S ...
随机推荐
- PRD文档怎么写
昨天学习PMP的相关文档,正好看到里面讲的PRD文档是怎么写的 就把一些学习过程,思维方式,还有用到的工具给记录下来 方便自己以后需要的时候,再去查阅,再读这个教程的时候,我顺便用脑图画了一下 脑图工 ...
- Ehcache缓存配置和基本使用
前言 在java项目广泛的使用中.它是一个开源的.设计于提高在数据从RDBMS中取出来的高花费.高延迟采取的一种缓存方案. 正因为Ehcache具有健壮性(基于java开发).被认证(具有apache ...
- HttpWebRequest抓取网页内容与直接输入URL得到的内容不一致!球大神帮忙!!
一.前言 我在做一个百度收录情况查询的软件,就是通过软件来批量查询文章链接是否被百度收录,主要是用来查询某个网址的收录次数还有网站的排行数,思路是借鉴别人的. 二.问题描述 首先需要考虑的是能够支持哪 ...
- 使用 Azure 资源管理器向 Windows VM 应用策略
通过使用策略,组织可以在整个企业中强制实施各种约定和规则. 强制实施所需行为有助于消除风险,同时为组织的成功做出贡献. 本文介绍如何使用 Azure 资源管理器策略,为组织中的虚拟机定义所需的行为. ...
- Oracle EBS AP取消核销
--取消核销 created by jenrry 20170425 DECLARE l_result BOOLEAN; l_msg_count NUMBER; l_result_n varchar2( ...
- 入坑Vue
长期的后端数据开发着实有些枯燥无趣,项目完工,闲暇之际,最近一直在研究前端方面的东西,不得感叹,前端技术发展速度快的让人有些目不暇接,从jQuery开启的插件化时代,几乎许多网站都被jQuery支配, ...
- asp.net获取当前网址url
asp.net获取当前网址url 设当前页完整地址是:http://www.jb51.net/aaa/bbb.aspx?id=5&name=kelli "http://" ...
- 什么是套接字(Socket)
应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要 通过同一个TCP协议端口传输数据.为了区别不同的应用程序进程和连 ...
- JRebel for Hybris ,Idea and Windows
参考: Jrebel官网参考地址:https://manuals.zeroturnaround.com/jrebel/standalone/hybris.html Wiki Hybris参考地址:ht ...
- MySQL运维之---mysqldump备份、select...into outfile、mysql -e 等工具的使用
1.mysqldump备份一个数据库 mysqldump命令备份一个数据库的基本语法: mysqldump -u user -p pwd dbname > Backup.sql 我们来讲解一下备 ...