题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=4556

题解:

巨恶心。。。但是题很好呀,可以练习好几个比较麻烦的算法~

1).预处理
首先用倍增算法求出 sa[],以及rank[],height[]。
并且对 height[]数组建立ST表。
按顺序对rank[]建立主席树。
(第i颗树的节点 u[l,r]保存了在 rank[1]~rank[i]这个前缀内,出现了多少个权值在 l~r内的rank值(num))

2).在线查询
对于一组询问(a,b,c,d),先二分答案 X,下面即是判定:
用rank[]数组得到后缀 c在后缀数组中的位置 P。
然后再求出在后缀数组中从p向上延伸到的最远位置 L,使得 LCP(L,P)>=X。
同理,向下延伸到最远位置 R,使得 LCP(P,R)>=X。
(求法呢,可以用二分,也可以用倍增求,类似倍增法求LCA,在求得时候需要用到 RMQ)
接下来,就要用到主席树了。
既然求出了与后缀c的LCP>=X的后缀在后缀数组中的排名范围[L,R]
那么就查询主席树 rt[a-1]~rt[b-X+1]中的权值区间 [L,R]的值num是否大于 0即可。
(如果 num>0,即表明在 S[a~b]内存在一个子串与后缀 c的LCP至少为 X)

复杂度:O(n*log2N*log2N),有点卡时间,BZOJ上花了 14S.

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100005
#define rint register int
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
char S[MAXN];
int sa[MAXN],rak[MAXN],hei[MAXN],stm[MAXN][20],log2[MAXN];
struct CMT{//Chairman Tree (QAQ)
int rt[MAXN],ls[MAXN*20],rs[MAXN*20],num[MAXN*20],siz;
void pushup(int u){
num[u]=num[ls[u]]+num[rs[u]];
}
void reset(int &u,int l,int r){
u=++siz; num[u]=0;
if(l==r) return;
int mid=(l+r)>>1;
reset(ls[u],l,mid);
reset(rs[u],mid+1,r);
}
void build(int &u,int l,int r,int p,int v){
u=++siz;
if(l==r){num[u]=1; return;}
ls[u]=ls[v]; rs[u]=rs[v];
int mid=(l+r)>>1;
if(p<=mid) build(ls[u],l,mid,p,ls[v]);
else build(rs[u],mid+1,r,p,rs[v]);
pushup(u);
}
int query(int lu,int ru,int l,int r,int al,int ar){//左开右闭
if(al<=l&&r<=ar) return num[ru]-num[lu];
int mid=(l+r)>>1,now=0;
if(al<=mid)
now+=query(ls[lu],ls[ru],l,mid,al,ar);
if(mid<ar)
now+=query(rs[lu],rs[ru],mid+1,r,al,ar);
return now;
}
}T;
void build(int N,int M){
static int ta[MAXN],tb[MAXN],c[MAXN],*x,*y; x=ta; y=tb;
for(rint i=0;i<M;i++) c[i]=0;
for(rint i=0;i<N;i++) c[x[i]=S[i]]++;
for(rint i=1;i<M;i++) c[i]+=c[i-1];
for(rint i=N-1;i>=0;i--) sa[--c[x[i]]]=i;
for(rint k=1;k<N;k<<=1){
int p=0;
for(rint i=N-k;i<N;i++) y[p++]=i;
for(rint i=0;i<N;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(rint i=0;i<M;i++) c[i]=0;
for(rint i=0;i<N;i++) c[x[y[i]]]++;
for(rint i=1;i<M;i++) c[i]+=c[i-1];
for(rint i=N-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y); y[N]=-1; M=1; x[sa[0]]=0;
for(rint i=1;i<N;i++)
x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?M-1:M++;
if(M>=N) break;
}
for(rint i=0;i<N;i++) rak[sa[i]+1]=i+1;
for(rint i=0,h=0,j;i<N;i++){
if(h) h--;
if(rak[i+1]>1){
j=sa[(rak[i+1]-1)-1];
while(S[i+h]==S[j+h]) h++;
}
stm[rak[i+1]][0]=hei[rak[i+1]]=h;
}
for(rint k=1;k<=log2[N];k++)
for(rint i=(1<<k);i<=N;i++)
stm[i][k]=min(stm[i-(1<<(k-1))][k-1],stm[i][k-1]);
}
int LCP(int l,int r){
if(l>r) swap(l,r); l++;
int k=log2[r-l+1];
return min(stm[l+(1<<k)-1][k],stm[r][k]);
}
int multiply_find(int p,int x,int y,int N){
int q=p;
for(rint k=log2[N],Q;k>=0;k--){
Q=q+(1<<k)*y;
if(Q<1||Q>N) continue;
if(LCP(Q,p)<x) continue;
q=Q;
}
return q;
}
bool check(int x,int a,int b,int c,int d,int N){
int L=multiply_find(rak[c],x,-1,N);
int R=multiply_find(rak[c],x,1,N);
int Lu=a-1,Ru=b-x+1;
return T.query(T.rt[Lu],T.rt[Ru],1,N,L,R);
}
int binary_ans(int l,int r,int a,int b,int c,int d,int N){
int mid,ans=0;
while(l<=r){
mid=(l+r)>>1;
if(check(mid,a,b,c,d,N)) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main()
{
//filein(str); fileout(str);
log2[1]=0;
for(rint i=2;i<=100000;i++) log2[i]=log2[i>>1]+1;
int N,M,a,b,c,d;
scanf("%d%d",&N,&M);
scanf("%s",S); build(N,300);
T.reset(T.rt[0],1,N);
for(rint i=0;i<N;i++)
T.build(T.rt[i+1],1,N,rak[i+1],T.rt[i]);
for(rint i=1,ans;i<=M;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a>b) swap(a,b); if(c>d) swap(c,d);
ans=binary_ans(1,min(d-c+1,b-a+1),a,b,c,d,N);
printf("%d\n",ans);
}
return 0;
}

●BZOJ 4556 [Tjoi2016&Heoi2016]字符串的更多相关文章

  1. Bzoj 4556: [Tjoi2016&Heoi2016]字符串

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

  2. BZOJ 4556: [Tjoi2016&Heoi2016]字符串(后缀数组 + 二分答案 + 主席树 + ST表 or 后缀数组 + 暴力)

    题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s ...

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556 本来只要查 ht[ ] 数组上的前驱和后继就行,但有长度的限制.可以二分答案解决!然后 ...

  4. BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案

    Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...

  5. 4556: [Tjoi2016&Heoi2016]字符串

    4556: [Tjoi2016&Heoi2016]字符串 链接 分析: 首先可以二分这个长度.此时需要判断是否存在一个以b结尾的前缀,满足与[c,d]的lcp大于等于mid. 如果我们把串翻转 ...

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

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

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

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

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

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

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

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

随机推荐

  1. MyGod_alpha版本测试报告

    买尬-Alpha版本测试报告 @(二手市场APP)[MyGod团队|团队项目|版本测试] 项目名称:武汉大学校园二手市场APP--买尬 软件版本:1.0.0 开发团队:MyGod 开发代表:程环宇 张 ...

  2. beta冲刺计划安排

    经过紧张的Alpha阶段,很多组已经从完全不熟悉语言和环境,到现在能够实现初步的功能.下一阶段即将加快编码进度,完成系统功能.强化软件工程的体会. 凡事预则立,在Beta开始前,以小组为单位,在敏捷冲 ...

  3. aws中的路由表

    参考官方文档: 由表中包含一系列被称为路由的规则,可用于判断网络流量的导向目的地. 在您的 VPC 中的每个子网必须与一个路由表关联:路由表控制子网的路由.一个子网一次只能与一个路由表关联,但您可以将 ...

  4. 第二篇:Python数据类型

    一.引子 1.什么是数据? x= #是我们要存储的数据 2.为何数据要分不同的类型 数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示 3.数据类型 数字(整型,长整型,浮点型,复数) 字 ...

  5. 《javascript设计模式与开发实践》阅读笔记(13)—— 职责链模式

    职责链模式 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 书里的订单的例子 假设我们负责一个售卖手机 ...

  6. PHP处理上传文件

    HTML中使用type = 'file'类型的表单可以向服务器上传文件: 上传文件的表单必须在form中定义enctyp = 'multipart/form-data': HTML代码如下: < ...

  7. EasyUI 动态创建对话框Dialog

    // 拒绝审批通过 function rejectApproval() { // 创建填写审批意见对话框 $("<div id='reject-comment'> </di ...

  8. Python内置函数(31)——object

    英文文档: class objectReturn a new featureless object. object is a base for all classes. It has the meth ...

  9. Spring知识点回顾(04)el 和资源使用

    注入普通字符 注入操作系统属性 注入表达式运算结果 注入其他bean属性 注入文件内容 注入网址内容 注入属性文件

  10. SpringMvc(4-1)Spring MVC 中的 forward 和 redirect

    Spring MVC 中,我们在返回逻辑视图时,框架会通过 viewResolver 来解析得到具体的 View,然后向浏览器渲染.通过配置,我们配置某个 ViewResolver 如下: <b ...