4556: [Tjoi2016&Heoi2016]字符串

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1360  Solved: 545
[Submit][Status][Discuss]

Description

佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了
一个长为n的字符串s,和m个问题。佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE
O,嫁给高富帅,走上人生巅峰。每个问题均有a,b,c,d四个参数,问你子串s[a..b]的所有子串和s[c..d]的最长公
共前缀的长度的最大值是多少?佳媛姐姐并不擅长做这样的问题,所以她向你求助,你该如何帮助她呢?

Input

输入的第一行有两个正整数n,m,分别表示字符串的长度和询问的个数。接下来一行是一个长为n的字符串。接下来
m行,每行有4个数a,b,c,d,表示询问s[a..b]的所有子串和s[c..d]的最长公共前缀的最大值。1<=n,m<=100,000,
字符串中仅有小写英文字母,a<=b,c<=d,1<=a,b,c,d<=n

Output

对于每一次询问,输出答案。

Sample Input

5 5
aaaaa
1 1 1 5
1 5 1 1
2 3 2 3
2 4 2 3
2 3 2 4

Sample Output

1
1
2
2
2

HINT

Source

[Submit][Status][Discuss]

无脑数据结构三合一,先建出数组求出height数组和ST表,然后二分答案,找到符合二分限制的名次范围,然后根据这个范围在主席树中找[a,b-mid+1]中是否存在解。

代码一长就出错,而且这道题我的程序常数不知道为什么是别人的两倍,试了各种卡常技巧都没用,最后在我准备放弃的最后一刻竟然A掉了:主席树查询不要写成que(rt[r])-que(rt[l-1]),而要写成que(rt[l-1],rt[r]),这样减少了重复定位的时间。这个优化比其它的register和数组维数互换等等方法效果明显的多。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define rg register int
#define rep(i,l,r) for (rg i=(l); i<=(r); i++)
using namespace std;const int N=200100;
int n,m,a,b,c,d,nd,h[N],x[N],y[N],s[N],sa[N],rt[N],rk[N],lg[N],ls[N*20],rs[N*20],sm[N*20],st[N][20];
char S[N];void rd(int &x){x=0; char ch=getchar();while (ch<'0' || ch>'9') ch=getchar();while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
}bool Cmp(rg l,rg r,rg k){ return l+k<=n && r+k<=n && y[l]==y[r] && y[l+k]==y[r+k]; }void build(rg m){memset(y,0,sizeof(y));rep(i,0,m) s[i]=0;rep(i,1,n) s[x[i]=S[i]-'a'+1]++;rep(i,1,m) s[i]+=s[i-1];for (rg i=n; i; i--) sa[s[x[i]]--]=i;for (rg k=1,p=0; p<n; k<<=1,m=p){p=0;rep(i,n-k+1,n) y[++p]=i;rep(i,1,n) if (sa[i]>k) y[++p]=sa[i]-k;rep(i,0,m) s[i]=0;rep(i,1,n) s[x[y[i]]]++;rep(i,1,m) s[i]+=s[i-1];for (rg i=n; i; i--) sa[s[x[y[i]]]--]=y[i];rep(i,1,n) y[i]=x[i]; p=1; x[sa[1]]=1;rep(i,2,n) x[sa[i]]=Cmp(sa[i],sa[i-1],k)?p:++p;}
}void getheight(){int k=0; rep(i,1,n) rk[sa[i]]=i;rep(i,1,n){for (rg j=sa[rk[i]-1]; i+k<=n && j+k<=n && S[i+k]==S[j+k]; k++);h[rk[i]]=k; if (k) k--;}
}void rmq(){rep(i,1,n) st[i][0]=h[i];rep(j,1,lg[n]) rep(i,1,n-(1<<j)+1) st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}void add(int y,int &x,int L,int R,int pos){x=++nd; sm[x]=sm[y]+1; ls[x]=ls[y]; rs[x]=rs[y];if (L==R) return; int mid=(L+R)>>1;if (pos<=mid) add(ls[y],ls[x],L,mid,pos); else add(rs[y],rs[x],mid+1,R,pos);
}int que(int y,int x,int L,int R,int l,int r){if (!x) return 0;if (L==l && r==R) return sm[x]-sm[y];int mid=(L+R)>>1;if (r<=mid) return que(ls[y],ls[x],L,mid,l,r);else if (l>mid) return que(rs[y],rs[x],mid+1,R,l,r);else return que(ls[y],ls[x],L,mid,l,mid)+que(rs[y],rs[x],mid+1,R,mid+1,r);
}int ask(rg l,rg r){ rg t=lg[r-l+1]; return min(st[l][t],st[r-(1<<t)+1][t]); }void getrange(rg x,int &l,int &r,rg mid){l=r=x;for (int i=17; ~i && r<n; i--) if (r+(1<<i)<=n && ask(x+1,r+(1<<i))>=mid) r=r+(1<<i);for (int i=17; ~i && l>1; i--) if (l-(1<<i)>=0 && ask(l-(1<<i)+1,x)>=mid) l=l-(1<<i);
}int jud(rg mid){int l,r; getrange(rk[c],l,r,mid);if (que(rt[l-1],rt[r],1,n,a,b-mid+1)>0) return 1; else return 0;
}int main(){freopen("bzoj4556.in","r",stdin);freopen("bzoj4556.out","w",stdout);scanf("%d%d%s",&n,&m,S+1);lg[1]=0; rep(i,2,n) lg[i]=lg[i>>1]+1;build(30); getheight(); rmq();rep(i,1,n) add(rt[i-1],rt[i],1,n,sa[i]);while (m--){rd(a); rd(b); rd(c); rd(d);if (!jud(1)) { printf("0\n"); continue; }int l=1,r=min(d-c+1,b-a+1),ans=0;while (l<r){int mid=(l+r)>>1;if (jud(mid)) ans=mid,l=mid+1; else r=mid;}if (jud(l)) printf("%d\n",l); else printf("%d\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/HocRiser/p/8654588.html

[BZOJ4556][TJOI2016HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)相关推荐

  1. poj 1743 二分答案+后缀数组 求不重叠的最长重复子串

    题意:给出一串序列,求最长的theme长度 (theme:完全重叠的子序列,如1 2 3和1 2 3  or  子序列中每个元素对应的差相等,如1 2 3和7 8 9) 要是没有差相等这个条件那就好办 ...

  2. [2020.11.26NOIP模拟赛]勇者的后缀【SA,RMQ,主席树,二分】

    正题 题目链接:https://www.luogu.com.cn/problem/U142356?contestId=37784 题目大意 一个字符串,询问给出(x,l,r)(x,l,r)(x,l,r ...

  3. Bzoj4556 [Tjoi2016Heoi2016]字符串

    Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 846  Solved: 327 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了 ...

  4. 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

    题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...

  5. H - Hello Ms. Ze(树状数组套主席树,线段树上二分)

    H - Hello Ms. Ze 给定nnn种不同的材料,第iii种材料有aia_iai​个,有mmm个操作,操作分为两类: 把第xxx种材料修改为yyy个, 只用[l,r][l, r][l,r]区间 ...

  6. zoj 2112 树状数组 套主席树 动态求区间 第k个数

    总算是把动态求区间第k个数的算法看明白了. 在主席树的基础上,如果有修改操作,则要通过套树状数组来实现任意区间求第k小的问题. 刚开始看不明白什么意思,现在有一点理解.树状数组的每个元素是一个线段树, ...

  7. 【BZOJ1901】Dynamic Rankings,树状数组套主席树

    Time:2016.05.09 Author:xiaoyimi 转载注明出处谢谢 传送门(权限) 题面 1901: Zju2112 Dynamic Rankings Time Limit: 10 Se ...

  8. ICPC 徐州 H Yuuki and a problem (树状数组套主席树)

    Yuuki and a problem 先不管第一问的修改操作,考虑如何达到第二问的查询操作, 题目要我们给出一个区间[l,r][l, r][l,r]中,不能通过权值+++得到的最小的数字是什么, 假 ...

  9. #279. [SYZOI Round1] 滑稽♂树(树状数组套主席树)

    #279. [SYZOI Round1] 滑稽♂树 子树上的问题,考虑dfsdfsdfs序,第kkk大,可以用主席树嘛,支持修改,那就树状数组上套主席树,参考P4175 [CTSC2008]网络管理( ...

最新文章

  1. 【pytorch】拟合sin函数
  2. redis cluster 集群重新启动关闭
  3. 类型与通用语言运行时
  4. WordPress Kyma plugin检测kyma连接状态的逻辑
  5. JavaFX图表(七)之散点图
  6. python文件的读取与写入_python中文件的读取与写入以及os模块
  7. 《Node.js区块链开发》
  8. jQuery源码研究分析学习笔记-回调函数(11)
  9. linux erlang安装教程,linux(CentOS7)中安装erlang(20.3)以及rabbitmq(3.6.15)的步骤以及一些注意事项...
  10. C#4.0新特性学习(四)—匿名方法及Lambda表达式
  11. 吾爱破解python百度文库下载源码_【原创源码】【python】淘豆网文档下载探索
  12. ActivityManager的作用
  13. 数学建模多元分析实例
  14. 社区征稿 | 价值3200RMB的DTCC门票免费送!
  15. 关于paypal账户限制的话题
  16. python设置桌面壁纸后重启电脑失效解决方案
  17. 如何高效使用Micropython看你喜欢看的视频?【下】(生成图片帧和WIFI传输播放)
  18. Zabbix-2.4-安装-1
  19. 《第一堂棒球课》:王牌二垒手·棒球4号位
  20. 阿里云服务器配置远程打印机,电脑启用打印服务器配置

热门文章

  1. php webstorm,webstorm和phpstorm的区别
  2. react mysql增删改查_react增删改查
  3. 网络宣传推广浅谈关键词排名好却没有流量的原因解决方法!
  4. 如何做网络推广浅析在网站优化中如更换域名该如何避免降权风险?
  5. 论网站长尾关键词优化的六大方法
  6. php 文档标示规范,php标识
  7. 写一个sql实现以下查询结果_SQL 优化极简法则,你掌握了几个?
  8. python中几种读取文件的方法_python 逐行读取文件的几种方法
  9. android .9 格式图片 背景设置 高度问题 空白问题
  10. 受限玻尔兹曼机——用在推荐系统里