题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556

本来只要查 ht[ ] 数组上的前驱和后继就行,但有长度的限制。可以二分答案解决!然后用主席树查区间内的 ht[ ] 的前驱和后继即可。(主席树弄对 rk 的权值线段树)

在主席树上走的复杂度应该不会比二分然后查看主席树的 log2 更差吧。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=1e5+,K=,M=N*K;
int n,sa[N],rk[N],tp[N],tx[N],ht[N][K],lg[N],bin[K];
int tot,ls[M],rs[M],sm[M],rt[N];
char s[N];
void Rsort(int n,int nm)
{
for(int i=;i<=nm;i++)tx[i]=;
for(int i=;i<=n;i++)tx[rk[i]]++;
for(int i=;i<=nm;i++)tx[i]+=tx[i-];
for(int i=n;i;i--)sa[tx[rk[tp[i]]]--]=tp[i];
}
void get_sa(int n)
{
int nm=;
for(int i=;i<=n;i++)tp[i]=i,rk[i]=s[i]-'a'+;
Rsort(n,nm);
for(int k=;;k<<=)
{
int tot=;
for(int i=n-k+;i<=n;i++)tp[++tot]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++tot]=sa[i]-k;
Rsort(n,nm);memcpy(tp,rk,sizeof rk);
nm=;rk[sa[]]=;
for(int i=;i<=n;i++)//i=2!!!!not i=1
{
int u=sa[i]+k,v=sa[i-]+k;// if(u>n)u=0; if(v>n)v=0;
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[u]==tp[v])?nm:++nm;
}
if(nm==n)break;
}
}
void get_ht(int n)
{
for(int i=,k=,j;i<=n;i++)
{
if(rk[i]==)continue;//
for((k?k--:),j=sa[rk[i]-];i+k<=n&&j+k<=n&&s[i+k]==s[j+k];k++);
//////i+k<=n&&j+k<=n
ht[rk[i]][0]=k;
}
for(int i=;i<=n;i++)lg[i]=lg[i>>]+;
bin[]=;for(int i=;i<=lg[n];i++)bin[i]=bin[i-]<<;
//i<=lg[n] not bin[i-1]<lg[n]!!!(should bin[i-1]<n)
for(int t=;t<=lg[n];t++)
for(int i=;i+bin[t]-<=n;i++)
ht[i][t]=Mn(ht[i][t-],ht[i+bin[t-]][t-]);
}
void ins(int &cr,int pr,int l,int r,int p)
{
cr=++tot;ls[cr]=ls[pr];rs[cr]=rs[pr];sm[cr]=sm[pr]+;
if(l==r)return; int mid=l+r>>;
if(p<=mid)ins(ls[cr],ls[pr],l,mid,p);
else ins(rs[cr],rs[pr],mid+,r,p);
}
int qry(int r1,int r2,int l,int r,int p)
{
if(sm[r2]-sm[r1]==)return ;
if(l==r)return l; int mid=l+r>>,d=;//d=0!!
if(p>mid)d=qry(rs[r1],rs[r2],mid+,r,p);
if(d)return d;
return qry(ls[r1],ls[r2],l,mid,p);
}
int qry2(int r1,int r2,int l,int r,int p)
{
if(sm[r2]-sm[r1]==)return ;
if(l==r)return l; int mid=l+r>>,d=;
if(p<=mid)d=qry2(ls[r1],ls[r2],l,mid,p);//qry2 not qry
if(d)return d;
return qry2(rs[r1],rs[r2],mid+,r,p);
}
int qry_ht(int l,int r)
{
if(l==r)return n-sa[l]+;//////n-sa[l]+1 not n-l+1!!!
int d=lg[r-l];
return Mn(ht[l+][d],ht[r-bin[d]+][d]);//l+1!!!not l
}
int main()
{
int Q;n=rdn();Q=rdn();scanf("%s",s+);//+1
get_sa(n);get_ht(n);
for(int i=;i<=n;i++)ins(rt[i],rt[i-],,n,rk[i]);
int l1,r1,l2,r2;
while(Q--)
{
l1=rdn();r1=rdn();l2=rdn();r2=rdn();
int l=,r=Mn(r1-l1+,r2-l2+),ans=;
while(l<=r)
{
int mid=l+r>>,d=r1-mid+;
int p1=qry(rt[l1-],rt[d],,n,rk[l2]);
int p2=qry2(rt[l1-],rt[d],,n,rk[l2]);
int tmp=Mx((p1?qry_ht(p1,rk[l2]):),(p2?qry_ht(rk[l2],p2):));
if(tmp>=mid)ans=mid,l=mid+;
else r=mid-;
}
printf("%d\n",ans);
}
return ;
}

bzoj 4556 [Tjoi2016&Heoi2016]字符串——后缀数组+主席树的更多相关文章

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

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

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

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

  3. [HEOI2016] 字符串 - 后缀数组,主席树,ST表,二分

    [HEOI2016] 字符串 Description 给定一个字符串 \(S\), 有 \(m\) 个询问,每个询问给定参数 \((a,b,c,d)\) ,求 \(s[a..b]\) 的子串与 \(s ...

  4. BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)

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

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

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

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

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

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

    [BZOJ4556][Tjoi2016&Heoi2016]字符串 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一 ...

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

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

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

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

随机推荐

  1. svn更新产生的异常

    同步svn时差生的错误如下:   同步 SVNStatusSubscriber 时报告了错误.1 中的 0 个资源已经同步. 同步 /tunnel14 时发生错误:Error getting stat ...

  2. CentOS搭建“加速器”

    1.安装Shadowsocks 服务端 yum -y update yum install -y python-setuptools && easy_install pip pip i ...

  3. php中点击网页不跳转执行程序

    if($code['result_code'] !='FAIL') { echo "<script type='text/javascript'> alert('退款成功,请耐心 ...

  4. 获取和设置消息队列的属性msgctl,删除消息队列

    消息队列的属性保存在系统维护的数据结构msqid_ds中,用户可以通过函数msgctl获取或设置消息队列的属性. int msgctl(int msqid, int cmd, struct msqid ...

  5. 文件属性,获取,设置文件属性chown stat函数

    转载:http://c.biancheng.net/cpp/html/326.html man 2 stat查看手册 int stat(const char *path, struct stat *b ...

  6. CSS中的长度单位及颜色表示

       CSS中的长度单位及颜色表示 长度单位: px:像素,绝对单位 em:相对单位,如果用于font-size属性本身,则是相对于父元素的font-size.若用于其他属性(width,height ...

  7. Python 数据类型--Bytes类型

    一.Bytes类型 在Python3以后,字符串和bytes类型彻底分开了.字符串是以字符为单位进行处理的,bytes类型是以字节为单位处理的. bytes数据类型在所有的操作和使用甚至内置方法上和字 ...

  8. IoC基础例子

    一个简单的例子: 一般新建一个com.dao包,存放一些dao接口. com.dao.impl里面存放具体的dao com.service存放service接口 com.service.impl具体的 ...

  9. mysql sum(if())用法

    原表:id    fenlei     time1      分类1      201303162      分类2      201303163      分类3      201303174    ...

  10. webstrom vue配置eslint

    (得出结论,还是得从官方文档中找,哇!!) 1.安装eslint插件,可以从search in repositories中获得,或者:http://plugins.jetbrains.com/plug ...