bzoj4556: [Tjoi2016&Heoi2016]字符串 (后缀数组加主席树)
题目是给出一个字符串,每次询问一个区间[a,b]中所有的子串和另一个区间[c,d]的lcp最大值,首先求出后缀数组,对于lcp的最大值肯定是rank[c]的前驱和后继,但是对于这个题会出现问题,就是题目中有区间的限制。
For example:
5 1
aaaab
1 2 3 5
对于这个样例,如果直接找到aab的前驱是 aaab,然后由于区间的原因答案是1,但是如果我们再往前找的话,找到aaaab,答案会变成2。那就出现了错误。考虑一下怎么做可以去除这种影响呢?
我们可以二分一下,首先对于[a,b]这个区间我们只考虑前一半区间[a,mid] 我们利用上面求前驱和后继的方法求出一个答案,如果答案大于mid我们就要考虑mid以前的区间,反之就考虑mid以后的区间。(这里的区间是指子串的左端点所在的区间)
为什么是对的?分类讨论一下,如果答案大于mid,那么我们不可能会考虑mid之后的区间,因为显然mid之后的区间到b的长度都小于mid,答案不会变优。如果答案小于mid,我们就不会在考虑mid之前的区间,因为算出答案小于mid,显然它不可能是由于区间限制得出的,因为我们只考虑前一半的区间,它到末尾的长度肯定大于等于mid,所以我们往后二分,因为随着区间的扩大我们找到的前驱和后继肯定会越来越接近rank[c],那么答案可能会变优,而我们往前判断答案肯定不会变优,所以往后二分。这样二分的正确性就ok了。(其实这个性质挺不好想的,我也是懵逼了半天,然而大奕哥用一个暴力碾掉了标算,bzoj上rank1......详情可以看博客 http://www.cnblogs.com/nbwzyzngyl/p/8215412.html 纯属侥幸......)
那么我们可以用主席树来办到求前驱和后继,这道题就解决了。—— by VANE
#include<bits/stdc++.h>
using namespace std;
const int N=;
const int M=;
int n,m,a[N],tax[N],tp[N],height[N],st[N][],Log[N];
int sa[N],rank[N],sum[M],ls[M],rs[M],siz,root[N],mm;
char s[N];
void rsort()
{
for(int i=;i<=m;++i) tax[i]=;
for(int i=;i<=n;++i) tax[rank[tp[i]]]++;
for(int i=;i<=m;++i) tax[i]+=tax[i-];
for(int i=n;i;--i) sa[tax[rank[tp[i]]]--]=tp[i];
}
bool cmp(int *f,int x,int y,int w){return max(x,y)+w<=n&&f[x]==f[y]&&f[x+w]==f[y+w];}
void suffix()
{
m=;for(int i=;i<=n;++i) tp[i]=i;
for(int i=;i<=n;++i) rank[i]=a[i];
rsort();
for(int w=,p;w<n;w+=w)
{
p=;for(int i=n-w+;i<=n;++i) tp[++p]=i;
for(int i=;i<=n;++i) if(sa[i]>w) tp[++p]=sa[i]-w;
rsort();swap(rank,tp);rank[sa[]]=p=;
for(int i=;i<=n;++i) rank[sa[i]]=cmp(tp,sa[i],sa[i-],w)?p:++p;
m=p;if(p>=n) break;
}
int j,k=;
for(int i=;i<=n;height[rank[i++]]=k)
for(k=k?k-:,j=sa[rank[i]-];a[j+k]==a[i+k];++k);
memset(st,,sizeof st);
for(int i=;i<=n;++i) st[i][]=height[i];
for(int j=;j<=;++j)
for(int i=;i+(<<j)-<=n;++i)
st[i][j]=min(st[i][j-],st[i+(<<j-)][j-]);
for(int i=,j=;i<=n;++i)
{
if(i==(<<j+)) ++j;
Log[i]=j;
}
}
int lcp(int x,int y)
{
if(x>y) swap(x,y);
int len=Log[y-x+];
int ret=min(st[x][len],st[y-(<<len)+][len]);
return ret;
}
void insert(int l,int r,int x,int &y,int z)
{
y=++siz;
sum[y]=sum[x]+;
ls[y]=ls[x];rs[y]=rs[x];
if(l==r) return;
int mid=l+r>>;
if(z<=mid) insert(l,mid,ls[x],ls[y],z);
else insert(mid+,r,rs[x],rs[y],z);
}
int query_sum(int l,int r,int x,int y,int le,int ri)
{
if(le>ri) return ;
if(l==le&&r==ri) return sum[y]-sum[x];
int mid=l+r>>;
if(ri<=mid) return query_sum(l,mid,ls[x],ls[y],le,ri);
if(le>mid) return query_sum(mid+,r,rs[x],rs[y],le,ri);
return query_sum(l,mid,ls[x],ls[y],le,mid)+query_sum(mid+,r,rs[x],rs[y],mid+,ri);
}
int query_pos(int l,int r,int x,int y,int p)
{
if(l==r) return l;
int mid=l+r>>;
if(sum[ls[y]]-sum[ls[x]]>=p) return query_pos(l,mid,ls[x],ls[y],p);
return query_pos(mid+,r,rs[x],rs[y],p-sum[ls[y]]+sum[ls[x]]);
}
int main()
{
//freopen("str.in","r",stdin);
//freopen("str.out","w",stdout);
scanf("%d%d",&n,&mm);
scanf("%s",s+);for(int i=;i<=n;++i) a[i]=s[i];
suffix();
int a,b,c,d,x,pre,sub;
for(int i=;i<=n;++i) insert(,n,root[i-],root[i],rank[i]);
while(mm--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
int l=,r=b-a+,maxn=,mid;
bool flag=;
while(l<=r)
{
mid=l+r>>;
x=query_sum(,n,root[a-],root[b-mid],,rank[c]-);
pre=x?query_pos(,n,root[a-],root[b-mid],x):-;
x=query_sum(,n,root[a-],root[b-mid],,rank[c]);
sub=query_pos(,n,root[a-],root[b-mid],+x);
if(x==sum[root[b-mid]]-sum[root[a-]]) sub=-;
int ans=;
if(pre!=-)
{
int o=min(lcp(pre+,rank[c]),b-sa[pre]+);
ans=max(ans,min(o,d-c+));
}
if(sub!=-)
{
int o=min(lcp(rank[c]+,sub),b-sa[sub]+);
ans=max(ans,min(o,d-c+));
}
if(c>=a&&c<=b) ans=max(ans,min(d,b)-c+);
maxn=max(maxn,ans);
if(ans>=mid) l=mid+;
else r=mid;
if(flag) break;
if(l==r) flag=;
}
printf("%d\n",maxn);
}
}
bzoj4556: [Tjoi2016&Heoi2016]字符串 (后缀数组加主席树)的更多相关文章
- 【BZOJ4556】[Tjoi2016&Heoi2016]字符串 后缀数组+二分+主席树+RMQ
[BZOJ4556][Tjoi2016&Heoi2016]字符串 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一 ...
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...
- Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 169 Solved: 87[Sub ...
- 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 657 Solved: 274[Su ...
- BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)
Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱 ...
- BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案
Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...
- bzoj 4556 [Tjoi2016&Heoi2016]字符串——后缀数组+主席树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556 本来只要查 ht[ ] 数组上的前驱和后继就行,但有长度的限制.可以二分答案解决!然后 ...
- 【BZOJ4556】字符串(后缀数组,主席树)
[BZOJ4556]字符串(后缀数组,主席树) 题面 BZOJ 题解 注意看题: 要求的是\([a,b]\)的子串和[c,d]的\(lcp\)的最大值 先来一下暴力吧 求出\(SA\)之后 暴力枚举\ ...
- 【BZOJ5304】[HAOI2018]字串覆盖(后缀数组,主席树,倍增)
[BZOJ5304][HAOI2018]字串覆盖(后缀数组,主席树,倍增) 题面 BZOJ 洛谷 题解 贪心的想法是从左往右,能选就选.这个显然是正确的. 题目的数据范围很好的说明了要对于询问分开进行 ...
随机推荐
- node、npm及node_modules中依赖的版本更新
好久没用node了,想重新拾起来发现node还有相关模块的版本都太低了,使用npm install全是报版本低的警告. 这里记录一下,版本管理和node_modules更新的方法. 我用的是Windo ...
- [\u4e00-\u9fa5] //匹配中文字符
[\u4e00-\u9fa5] //匹配中文字符 ^[1-9]\d*$ //匹配正整数^[A-Za-z]+$ //匹配由26个英文字母组成的字符串^[A-Z]+$ //匹配由26 ...
- 使用Sass预定义一些常用的样式,非常方便
CSS预处理技术现在已经非常成熟,比较流行的有Less,Sass,Stylus,在开发过程中提升我们的工作效率,缩短开发时间,方便管理和维护代码,可以根据自己的喜好选择一款自己喜欢的工具开发,使用很接 ...
- 蓝色简单的cms文档管理系统模板——后台
链接:http://pan.baidu.com/s/1qYMwHis 密码:xyiw
- 模型稳定度指标PSI与IV
由于模型是以特定时期的样本所开发的,此模型是否适用于开发样本之外的族群,必须经过稳定性测试才能得知.稳定度指标(population stability index ,PSI)可衡量测试样本及模型开发 ...
- oracle查看表中数据的大小
通过从视图 user_segments的字段 bytes中找到 select SUM(bytes)/1024/1024 from user_segments where segment_name='E ...
- imperva系统升级遇见的错误(配置文件的导入导出)
今天心态有点炸了 今天去东兴证券做waf升级.浪费了两天才弄完.把客户都弄得有点急了.好歹原厂的工程师耐心的讲解这才弄完.感谢路哥.... 赶紧总结一下. 事情是这样的.东兴 证券的imperva是v ...
- MySQL sleep过多解决方法
睡眠连接过多,会对mysql服务器造成什么影响? 严重消耗mysql服务器资源(主要是cpu, 内存),并可能导致mysql崩溃. 造成睡眠连接过多的原因? 1. 使用了太多持久连接(个人觉得,在高并 ...
- URL中斜杠/和反斜杠\的区别小结
Unix使用斜杆/ 作为路径分隔符,而web应用最新使用在Unix系统上面,所以目前所有的网络地址都采用 斜杆/ 作为分隔符. Windows由于使用 斜杆/ 作为DOS命令提示符的参数标志了,为了不 ...
- Linux 基础——压缩解压命令
时间过的真快,周末不会学习Linux,每天就是下班后学习.这周工作很忙,要几天总结一次了. 一.处理数据文件 sort dest:将目标文件的内容进行排序,默认是按字符顺序排序的. sort -n d ...