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 ...
随机推荐
- UI第二组与数据库对接时遇到的问题记录
此为组内某一位做UI的同学的随笔. 之前的app由于没有加入数据库,所以每次重新启动里面的东西都会回到初始状态,即不能保存内容.我们的数据库小组已经很棒地基本完成了数据库的工作,于是我就准备加入数据库 ...
- Zabbix添加Ping外网IP监控
1.先添加一个HOST,只填写IP即可,如10.1.1.1 2.选择一台客户端,新建item,如下: 3.新建trigger: 注:icmpping[<target>,<packet ...
- Android5.0中Material Design的新特性
最近项目中需要用到Material Design,整理了下面几个常用的控件,以便记忆. 一.Snackbar 1.作用:与Toast类似,但是可以点击监听: 2.使用: (1)Snackbar调用静态 ...
- C语言编程积累2
版权声明:本文为CSDN博主(天才2012)原创文章,未经博主同意不得转载. https://blog.csdn.net/gzzaigcn/article/details/27113957 寥寥数笔, ...
- Android Studio快捷键——编辑篇
Android Studio是官方推出的Android开发IDE,本系列讲解Android Studio中常用的快捷键,本文是该系列的第一篇,讲解的内容是与编辑代码相关的快捷键. 本文所讲快捷键基于A ...
- Common lang一些边界方法总结(好记性不如烂笔头,需要慢慢积累).一定要利用好现有的轮子,例如Apache common与Google Guava
好记性真是不如烂笔头啊!!!! 如下代码: List<String> list = new ArrayList<String>(); list.add("1" ...
- Linux命令——文件和目录管理
Linux命令--文件和目录管理 基本命令 命令ls 作用:显示目录下的文件和文件夹 说明:默认显示当前目录,可跟路径参数 参数:-a,显示隐藏目录 参数:-l,显示文件权限 参数:-d,显示文件最后 ...
- WorldWind源码剖析系列:视景体类Frustum
PluginSDK中的视景体类Frustum是三维计算机图形学中的概念,主要用来描述透视投影的过程.三维计算机图形学中关于三维物体的渲染,Direct3D和OpenGL都是先通过对现实世界中的场景先进 ...
- 【转】SQL 常用关键字释义和用法
转自: http://blog.csdn.net/iamwangch/article/details/8093933 下面 是 从网络上整理 出来的 SQL 关键字和 常用函数的 释义和简单用 ...
- Python2.7-sqlite3
sqlite3模块,SQLite 是用 C 写的轻量级的数据库,sqlite3 模块提供了对数据库的接口,要使用必须首先创建一个 Connection 对象,代表连接至数据库,然后才能继续操作,操作数 ...