题链:

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. 数据结构基础——结构体struct及类型别名typedef的使用

    一.结构体的创建 在C语言中,实现数据结构的一种常用方法便是使用结构体(structure)其示例代码如下: struct stu { int num; char ch; }; struct表示创建结 ...

  2. 第二次作业:APP案例分析

    App案例分析 产品:三国杀-页游手游双通 选择理由 当今社会手机已经渐渐取代了电脑在人们日常生活的需求,既然要选择APP进行案例分析,首推的估计就是手机APP了.三国杀是陪伴我高中时代的主要娱乐方式 ...

  3. 201621123068 Week03-面向对象入门

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识点组织起来.请使用工具画出本周学习到的知识点及知识点之间的联系.步骤如下: 1.1 写出你 ...

  4. 20145237《Java程序设计》第一周学习总结

    教材学习内容总结 java可分为Java SE.Java EE.Java ME三大平台. java SE分为JVM.JRE.JDK.与java语言四个部分. JRE包括java SE API和JVM. ...

  5. scrapy 模拟登陆

    import scrapy import urllib.request from scrapy.http import Request,FormRequest class LoginspdSpider ...

  6. display属性

    display 属性规定元素应该生成的框的类型. 值 描述 none 此元素不会被显示. block 此元素将显示为块级元素,此元素前后会带有换行符. inline 默认.此元素会被显示为内联元素,元 ...

  7. Vue filter介绍及详细使用

    Vue filter介绍及其使用 VueJs 提供了强大的过滤器API,能够对数据进行各种过滤处理,返回需要的结果. Vue.js自带了一些默认过滤器例如: capitalize 首字母大写 uppe ...

  8. 消除ExtJS6的extjs-trila字样

  9. CentOS 7 使用yum安装出现错误

    CentOS 7 使用yum安装软件出现错误: Loaded plugins: fastestmirror 此错误信息可能是因为DNS配置错误,可以通过更改配置文件来解决: 1. 使用vi打开DNS的 ...

  10. C#之Socket通信

    0.虽然之前在项目中也有用过Socket,但始终不是自己搭建的,所以对Server,Clinet端以及心跳,断线重连总没有很深入的理解,现在自己搭建了一遍加深一下理解. 服务端使用WPF界面,客户端使 ...