点此看题面

大致题意: 给你一个字符串\(s\),每次问你一个子串\(s[a..b]\)的所有子串和\(s[c..d]\)的最长公共前缀。

二分

首先我们可以发现一个简单性质,即要求最长公共前缀,则我们必然取\(s[a..b]\)的一个子串\(s[x..b]\),因为求最长公共前缀取长了不会影响答案。

那么如果我们二分答案\(mid\),就变成了每次判断原串第\(c\)个后缀长度为\(mid\)的前缀是否是原串第\(a\sim b-mid+1\)个后缀中某一后缀的前缀。

后缀自动机+线段树合并

考虑我们先建一棵后缀树(就是对原串的倒串建一个后缀自动机)。

然后,我们对于每一个节点,开一棵线段树维护其子树内有哪些后缀。

这可以通过线段树合并轻松预处理。

接下来,对于每次判断,我们找到第\(c\)个后缀所对应的节点,树上倍增找到其祖先中长度大于等于\(mid\)且长度最小的祖先,然后判断其子树内是否存在第\(a\sim b-mid+1\)个后缀中的某一后缀即可。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LN 20
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
int n;string s;
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
I void reads(string& x) {x="";W(isspace(c=tc()));W(x+=c,!isspace(c=tc())&&~c);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
template<int SZ> class SuffixAutomation//后缀自动机
{
private:
template<int PS> class SegmentTree//线段树
{
private:
#define L l,mid,S[rt][0]
#define R mid+1,r,S[rt][1]
#define PU(x) (V[x]=V[S[x][0]]|V[S[x][1]])
int n,tot,S[PS+5][2],V[PS+5];
I void Ins(CI p,CI l,CI r,int& rt)//插入元素
{
if(!rt&&(rt=++tot),l==r) return (void)(V[rt]=1);RI mid=l+r>>1;
p<=mid?Ins(p,L):Ins(p,R),PU(rt);
}
I bool Check(CI tl,CI tr,CI l,CI r,CI rt)//检验tl~tr之间是否有1
{
if(!rt) return 0;if(tl<=l&&r<=tr) return V[rt];RI mid=l+r>>1;
return (tl<=mid&&Check(tl,tr,L))||(tr>mid&&Check(tl,tr,R));
}
I int Merge(CI x,CI y,CI l,CI r)//线段树合并
{
if(!x||!y) return x+y;RI rt=++tot,mid=l+r>>1;V[rt]=V[x]|V[y];if(l==r) return rt;
S[rt][0]=Merge(S[x][0],S[y][0],l,mid),S[rt][1]=Merge(S[x][1],S[y][1],mid+1,r);return rt;
}
public:
I void Init(CI _n) {n=_n;}I void Ins(int& rt,CI p) {Ins(p,1,n,rt);}
I int Merge(CI x,CI y) {return Merge(x,y,1,n);}
I int Check(CI rt,CI l,CI r) {return Check(l,r,1,n,rt);}
#undef L
};
int n,lst,tot,pos[SZ+5],s[SZ<<1],t[SZ<<1];struct node {int Rt,L,F[LN],S[30];}O[SZ<<1];
SegmentTree<SZ*LN<<1> S;
public:
I SuffixAutomation() {lst=tot=1;}I void Init(CI _n) {S.Init(n=_n);}
I void Insert(CI id,CI x)//插入元素
{
RI now=++tot,p=lst,q;O[pos[id]=now=lst=tot].L=O[p].L+1,S.Ins(O[now].Rt,id);
W(p&&!O[p].S[x]) O[p].S[x]=now,p=O[p].F[0];if(!p) return (void)(O[now].F[0]=1);
if(O[p].L+1==O[q=O[p].S[x]].L) return (void)(O[now].F[0]=q);
RI k=++tot;O[k].L=O[p].L+1,O[k].F[0]=O[q].F[0],O[now].F[0]=O[q].F[0]=k,
memcpy(O[k].S,O[q].S,sizeof(O[q].S));W(p&&O[p].S[x]==q) O[p].S[x]=k,p=O[p].F[0];
}
I void Work()//预处理
{
#define Rsort() for(i=1;i<=tot;++i) ++t[O[i].L];\
for(i=1;i<=n;++i) t[i]+=t[i-1];for(i=tot;i;--i) s[t[O[i].L]--]=i;//基数排序
RI i,j;Rsort();for(i=1;i<=tot;++i) for(j=1;j<=LN;++j) O[s[i]].F[j]=O[O[s[i]].F[j-1]].F[j-1];//预处理倍增祖先
for(i=tot;i;--i) O[s[i]].F[0]&&(O[O[s[i]].F[0]].Rt=S.Merge(O[O[s[i]].F[0]].Rt,O[s[i]].Rt));//线段树合并,处理子树内有哪些后缀
}
I bool Check(CI k,CI l,CI r,CI id)//检验
{
RI i,x=pos[id];for(i=LN;~i;--i) O[O[x].F[i]].L>=k&&(x=O[x].F[i]);//倍增找到合法祖先
return S.Check(O[x].Rt,l,r);//线段树上查询
}
};
SuffixAutomation<N> S;
int main()
{
RI Qt,i,x1,y1,x2,y2,l,r,mid;F.read(n,Qt),F.reads(s);
for(S.Init(n),i=n;i;--i) S.Insert(i,s[i-1]&31);S.Work();W(Qt--)//建后缀自动机,注意用倒串
{
F.read(x1,y1,x2,y2),l=0,r=min(y1-x1+1,y2-x2+1);//读入
W(l<r) mid=l+r+1>>1,S.Check(mid,x1,y1-mid+1,x2)?l=mid:r=mid-1;//二分
F.writeln(l);//输出
}return F.clear(),0;
}

【BZOJ4556】[TJOI2016&HEOI2016] 字符串(后缀自动机+线段树合并+二分)的更多相关文章

  1. 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 657  Solved: 274[Su ...

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

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

  3. 模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)

    模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合) Code: #include <bits/stdc++.h> using namespace std; #define ...

  4. bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并)

    bzoj5417/luoguP4770 [NOI2018]你的名字(后缀自动机+线段树合并) bzoj Luogu 给出一个字符串 $ S $ 及 $ q $ 次询问,每次询问一个字符串 $ T $ ...

  5. BZOJ3413: 匹配(后缀自动机 线段树合并)

    题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直 ...

  6. cf666E. Forensic Examination(广义后缀自动机 线段树合并)

    题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并 首先对所有的\(t_i\)建个广义后缀自动机,这样可以得到所有子串信息. 考虑把询问离线,然后把\(S\)拿到自动机上跑,同时维护一下 ...

  7. [Luogu5161]WD与数列(后缀数组/后缀自动机+线段树合并)

    https://blog.csdn.net/WAautomaton/article/details/85057257 解法一:后缀数组 显然将原数组差分后答案就是所有不相交不相邻重复子串个数+n*(n ...

  8. 字符串(tjoi2016,heoi2016,bzoj4556)(sam(后缀自动机)+线段树合并+倍增+二分答案)

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

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

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

随机推荐

  1. es6模板字符串使用使${} 来包裹一个变量或者一个表达式

    es6模板字符串使用使${} 来包裹一个变量或者一个表达式 2019-04-28 14:33:54 Gabriel_wei 阅读数 1774  收藏 更多 分类专栏: 前端   版权声明:本文为博主原 ...

  2. 一起学react (1) 10分钟 让你dva从入门到精通

    前言 如果文章中有错误的地方的话 可以直接加我QQ:469373256 自己针对一些问题做的优化版本 目前刚启动 还不是很成熟 https://github.com/fangkyi03/fastkit ...

  3. RMAN详细教程(三):备份脚本的组件和注释

    RMAN详细教程(一):基本命令代码 RMAN详细教程(二):备份.检查.维护.恢复 RMAN详细教程(三):备份脚本的组件和注释 RMAN详细教程(四):备份脚本实战操作 一.基本组件: 1.Ser ...

  4. Jenkins操作学习 -- 配置及使用

    一.jenkins基本配置 1.在Jenkins首页,点击Manage Jenkins,然后再点击Manage Plugins插件管理,安装必要的插件.这里我只需要安装Git,因为第一次初始化安装没成 ...

  5. [06]ASP.NET Core中的进程内(InProcess)托管

    ASP.NET Core 进程内(InProcess)托管 本文作者:梁桐铭- 微软最有价值专家(Microsoft MVP) 文章会随着版本进行更新,关注我获取最新版本 本文出自<从零开始学 ...

  6. NOI2019退役记 upd:2019.12.1

    (我把原来写的东西全部删掉了) AFO. 我退役了,\(\mbox{yyb}\)退役了. 至少,在接下来的日子里,我得投身到文化课,度过快乐的高三生活了. 这两年的\(OI\)生涯给了我很多,让我学会 ...

  7. SpringCloud的入门学习之Eureka(Eureka的单节点)

    SpringCloud--->Spring生态体系的微服务架构:https://spring.io/ 官网贴图,如下所示,介绍了微服务的架构体系(话说,英语好读官网,可能很爽吧,没体验过). 1 ...

  8. StreamWriter StreamReader

    private void WriteLoginJsonData(object jsonData) { using (FileStream writerFileStream = new FileStre ...

  9. .NET MVC5简介(四)Filter和AuthorizeAttribute权限验证

    在webform中,验证的流程大致如下图: 在AOP中: 在Filter中: AuthorizeAttribute权限验证 登录后有权限控制,有的页面是需要用户登录才能访问的,需要在访问页面增加一个验 ...

  10. 诚聘.NET架构师、高级开发工程师(2019年8月29日发布)

    招聘单位是ABP架构设计交流群(134710707)群主阳铭所在的公司 公司简介 七二四科技有限公司成立于2015年,成立之初便由金茂资本按估值2亿投资2200万,进行“健康724”平台搭建,2017 ...