bzoj 4556 [Tjoi2016&Heoi2016]字符串——后缀数组+主席树
题目: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]字符串——后缀数组+主席树的更多相关文章
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...
- BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案
Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...
- [HEOI2016] 字符串 - 后缀数组,主席树,ST表,二分
[HEOI2016] 字符串 Description 给定一个字符串 \(S\), 有 \(m\) 个询问,每个询问给定参数 \((a,b,c,d)\) ,求 \(s[a..b]\) 的子串与 \(s ...
- BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)
Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱 ...
- Bzoj 4556: [Tjoi2016&Heoi2016]字符串
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 177 Solved: 92[Sub ...
- Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 169 Solved: 87[Sub ...
- 【BZOJ4556】[Tjoi2016&Heoi2016]字符串 后缀数组+二分+主席树+RMQ
[BZOJ4556][Tjoi2016&Heoi2016]字符串 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一 ...
- BZOJ 4556: [Tjoi2016&Heoi2016]字符串(后缀数组 + 二分答案 + 主席树 + ST表 or 后缀数组 + 暴力)
题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s ...
- bzoj4556: [Tjoi2016&Heoi2016]字符串 (后缀数组加主席树)
题目是给出一个字符串,每次询问一个区间[a,b]中所有的子串和另一个区间[c,d]的lcp最大值,首先求出后缀数组,对于lcp的最大值肯定是rank[c]的前驱和后继,但是对于这个题会出现问题,就是题 ...
随机推荐
- OAF 获取页面路径
--模糊查询某个页面 SELECT * FROM JDR_PATHS jp WHERE JP.PATH_NAME LIKE '%XXXX%'; --精确的查找过程 -- DocID --参数通过关于此 ...
- 在linux中,如何增加、修改、删除、暂停和冻结用户名
在Linux中,如何增加.修改.删除.暂停和冻结用户名 在操作增加.修改和删除用户名前,先认识linux中两个最重要的文件,它们就是账号管理最重要文件“/etc/passwd”与“etc/shadow ...
- sgu107. 987654321 problem 简单打表 难度:0
107. 987654321 problem time limit per test: 0.25 sec. memory limit per test: 4096 KB For given numbe ...
- bzoj3040
题解: 模板题,地界特斯拉+堆优化 注意第一种建边 代码: #include<bits/stdc++.h> using namespace std; typedef long long l ...
- L1-041 寻找250
对方不想和你说话,并向你扔了一串数…… 而你必须从这一串数字中找到“250”这个高大上的感人数字. 输入格式: 输入在一行中给出不知道多少个绝对值不超过1000的整数,其中保证至少存在一个“250”. ...
- DevExpress v17.2新版亮点—WinForms篇(五)
用户界面套包DevExpress v17.2终于正式发布,本站将以连载的形式为大家介绍各版本新增内容.开篇介绍了DevExpress WinForms v17.2 Data Grid Control ...
- bjui的ajax form不使用validate的表单验证
当form使用data-toggle为ajaxform或者是validate的时候,表单的onSubmit()和submit按钮的click()事件明明return false:还是会提交. 如果将d ...
- 安装Linux Mint17
韩总有台笔记本之前安装的是Win7,结果被她用成含毒,含马的机器了,最后干脆机器操作不了,愤怒的韩总把戴尔骂了个痛快并保证以后再也不用戴尔的笔记本了,然后愉快的换了一台新电脑,这台机器便放在我这里没人 ...
- django中的ajax组件
目录 django中的ajax 向服务器发送请求的途径 Ajax的特点 基于jquery实现的ajax请求 利用ajax实现计算器 利用ajax实现登陆认证 利用form表单进行文件上传 利用ajax ...
- Java快速排序和归并排序详解
快速排序 概述 快速排序算法借鉴的是二叉树前序遍历的思想,最终对数组进行排序. 优点: 对于数据量比较大的数组排序,由于采用的具有二叉树二分的思想,故排序速度比较快 局限 只适用于顺序存储结构的数据排 ...