Description

佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了
一个长为n的字符串s,和m个问题。佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE
O,嫁给高富帅,走上人生巅峰。每个问题均有a,b,c,d四个参数,问你子串s[a..b]的所有子串和s[c..d]的最长公
共前缀的长度的最大值是多少?佳媛姐姐并不擅长做这样的问题,所以她向你求助,你该如何帮助她呢?

Input

输入的第一行有两个正整数n,m,分别表示字符串的长度和询问的个数。接下来一行是一个长为n的字符串。接下来
m行,每行有4个数a,b,c,d,表示询问s[a..b]的所有子串和s[c..d]的最长公共前缀的最大值。1<=n,m<=100,000,
字符串中仅有小写英文字母,a<=b,c<=d,1<=a,b,c,d<=n
 

Output

对于每一次询问,输出答案。

Sample Input

5 5
aaaaa
1 1 1 5
1 5 1 1
2 3 2 3
2 4 2 3
2 3 2 4

Sample Output

1
1
2
2
2
 
考虑将串逆序后使用后缀自动机来做,对于每个询问我们可以二分一下答案len,然后倍增到SAM上的对应节点,这是我们发现只要判断该节点的right集中是否包含[a,b-len+1]中的元素即可。这个用棵线段树合并什么的东西预处理一下每个节点的right集就好了,时间复杂度为O(Nlog^2N)。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=200010;
const int maxnode=4000010;
int n,m,root[maxn],pos[maxn],c[maxn],od[maxn];
int ls[maxnode],rs[maxnode],ToT;
int to[maxn][26],anc[maxn][20],l[maxn],fa[maxn],cnt=1,last=1;
void insert(int& y,int l,int r,int p) {
y=++ToT;if(l==r) return;int mid=l+r>>1;
if(p<=mid) insert(ls[y],l,mid,p);
else insert(rs[y],mid+1,r,p);
}
int merge(int x,int y) {
if(!x) return y;
if(!y) return x;
int z=++ToT;
ls[z]=merge(ls[x],ls[y]);
rs[z]=merge(rs[x],rs[y]);
return z;
}
int query(int x,int l,int r,int ql,int qr) {
if(!x) return 0;
if(ql<=l&&r<=qr) return 1;
int mid=l+r>>1;
if(ql<=mid&&query(ls[x],l,mid,ql,qr)) return 1;
if(qr>mid&&query(rs[x],mid+1,r,ql,qr)) return 1;
}
void extend(int c,int val) {
int p=last,q,np,nq;l[last=np=++cnt]=l[p]+1;
insert(root[np],1,n,val);pos[val]=np;
for(;!to[p][c];p=fa[p]) to[p][c]=np;
if(!p) fa[np]=1;
else {
q=to[p][c];
if(l[p]+1==l[q]) fa[np]=q;
else {
l[nq=++cnt]=l[p]+1;
fa[nq]=fa[q];fa[q]=fa[np]=nq;
memcpy(to[nq],to[q],sizeof(to[q]));
for(;to[p][c]==q;p=fa[p]) to[p][c]=nq;
}
}
}
char str[maxn];
int check(int x,int a,int b,int p) {
dwn(i,19,0) if(x<=l[anc[p][i]]) p=anc[p][i];
return query(root[p],1,n,a,b-x+1);
}
int main() {
n=read();m=read();
scanf("%s",str+1);
dwn(i,n,1) extend(str[i]-'a',i);
rep(i,1,cnt) c[l[i]]++;
rep(i,1,n) c[i]+=c[i-1];
dwn(i,cnt,1) od[c[l[i]]--]=i;
dwn(i,cnt,1) root[fa[od[i]]]=merge(root[fa[od[i]]],root[od[i]]);
rep(i,1,cnt) {
int x=od[i];anc[x][0]=fa[x];
rep(j,1,19) anc[x][j]=anc[anc[x][j-1]][j-1];
}
while(m--) {
int a=read(),b=read(),x=read(),y=read();
int l=0,r=min(y-x+1,b-a+1)+1,mid;
while(l+1<r) if(check(mid=l+r>>1,a,b,pos[x])) l=mid; else r=mid;
printf("%d\n",l);
}
return 0;
}

  

BZOJ4556: [Tjoi2016&Heoi2016]字符串的更多相关文章

  1. [BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1360  Solved: 545[S ...

  2. Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 169  Solved: 87[Sub ...

  3. [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...

  4. [BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1215  Solved: 484[S ...

  5. BZOJ4556 [Tjoi2016&Heoi2016]字符串 SA ST表 二分答案 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4556.html 题目传送门 - BZOJ4556 题意 给定一个长度为 $n$ 的字符串 $s$ . ...

  6. 2019.02.27 bzoj4556: [Tjoi2016&Heoi2016]字符串(二分答案+sam+线段树合并)

    传送门 题意:给一个字符串SSS. 有mmm次询问,每次给四个参数a,b,c,da,b,c,da,b,c,d,问s[a...b]s[a...b]s[a...b]的所有子串和s[x...y]s[x... ...

  7. bzoj4556: [Tjoi2016&Heoi2016]字符串 (后缀数组加主席树)

    题目是给出一个字符串,每次询问一个区间[a,b]中所有的子串和另一个区间[c,d]的lcp最大值,首先求出后缀数组,对于lcp的最大值肯定是rank[c]的前驱和后继,但是对于这个题会出现问题,就是题 ...

  8. BZOJ4556 Tjoi2016&Heoi2016 字符串【后缀自动机+倍增+线段树合并】

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开 ...

  9. BZOJ4556 [Tjoi2016&Heoi2016]字符串 【后缀数组 + 主席树 + 二分 + ST表】

    题目 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职 ...

随机推荐

  1. html5 离线存储 worker

    html5 离线存储 <!DOCTYPE html> <html manifest="cache.manifest"> <!--manifest存储- ...

  2. 用rlwrap使sqlplus可以上下翻页

    下载rlwrap-0.30 从光盘上安装readline-devel和readline 安装rlwrap: #tar -zxvf rlwrap-0.30.tar.gz#cd rlwrap-0.30#. ...

  3. 在ubuntu中安装jdk

    安装环境 操作系统:ubuntu 14.04.1 server amd64 下载jdk wget http://download.oracle.com/otn-pub/java/jdk/7u67-b0 ...

  4. Boost练习程序(multi_index_container)

    代码来自:http://blog.csdn.net/whuqin/article/details/8482547 该容器能实现多列索引,挺好. #include <string> #inc ...

  5. 利用Visual GDB在Visual Studio中进行Android开发

    转载请注明http://www.cnblogs.com/adong7639/p/4119467.html 无意中发现了Visual GDB这个工具,可以再Visual Studio中进行Android ...

  6. 数字信号处理实验(零)—— 一维声音信号处理和二维图像处理

    一.在matlab下声音信号的I/O 1.读wav文件函数 •y = wavread('filename') •[y,Fs,bits] = wavread('filename') •[...] = w ...

  7. 智能车学习(一)—— 硬件准备

    一.硬件环境准备 1.烧写器焊接 (1)原理图: (2)焊接成品图 2.电源模块: 3.屏幕+键盘 4.单片机 二.软件环境准备 1.安装air6.7 2.安装JLINK驱动 3.安装软件包寄存在GI ...

  8. 【项目总结】之——导出Excel

    近来接手的项目,有几个很值得分享的东西.经过自己的不懈实践,总结,分享给大家,希望能对大家的学习有点帮助. 本次探讨的是mvc框架之中的一种导出方法,导出excel. 先让大家看一下啊我们的view界 ...

  9. 滚动到底部加载更多及下拉刷新listview的使用

    最新内容建议直接访问原文:滚动到底部加载更多及下拉刷新listview的使用 本文主要介绍可同时实现下拉刷新及滑动到底部加载更多的ListView的使用. 该ListView优点包括:a. 可自定义下 ...

  10. 端口偷窃(Port Stealing)技术

    端口偷窃(Port Stealing)技术   该技术主要用于局域网中间人攻击中,尤其目标计算机采用静态ARP后,导致ARP欺骗无效.   背景知识:路由器为了方便转发数据包,会在内部记录每个接口和M ...