4453: cys就是要拿英魂!

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 90  Solved: 46
[Submit][Status][Discuss]

Description

pps又开始dota视频直播了!一群每天被pps虐的蒟蒻决定学习pps的操作技术,他们把pps在这局放的技能记录了下
来,每个技能用一个字符表示。经过研究,蒟蒻们发现字典序更大的连招威力更大。于是所有蒟蒻都想学习pps最
强的连招。但是他们太弱了,不能学会整个视频里的连招,只能学会陈老师一段区间间内的连招,可是这个他们求
不出,于是只好向你求助。为了蒟蒻们不再被pps虐(怎么可能),请你帮帮他们。简化题意:给你一个字符串,
每次询问你一段区间的字典序最大的子串。

Input

第一行是一个字符串S,表示pps放的技能
第二行一个正整数Q,表示询问个数
接下来Q行,每行两个正整数[l,r],表示询问区间[l,r]中的字典序最大的子串。

Output

Q行,每行一个正整数,表示该区间内字典序最大的子串的起始位置。

Sample Input

Lets_go_mod_p!
5
2 2
3 3
2 5
1 10
2 9

Sample Output

2
3
3
3
3
数据范围:
1<=|S|<=100000
1<=Q<=100000
1<=l<=r<=|S|

讲课的时候方法大体明白,但是不明白怎么用可删除并查集实现
于是又找题解和代码研究了一遍,学到好多神奇的东西
 
CA爷好强:http://blog.csdn.net/creationaugust/article/details/51037027
题解:https://post.icpc-camp.org/d/142-neerc-2012-moscow-subregional-d-darkwing-duck/3
 
感觉上面有的地方说的让人有点不太好.....
这种求最大一个方法就是按询问右端点维护单调栈然后在单调栈里二分吧(二分找>=l的第一个,因为是递减的栈)
观察一段区间内,对于两个i<j,sufi<sufj,但是r<j+lcp(i,j)时这段区间i是大于j的,所以i应该保留
当r到了j+lcp(i,j)时,这个i就要删去了
支持任意位置删除的单调栈?linkct讲的可以用可删除并查集然而并不明白
这里的方法是用set维护“当前应该在栈里的元素”,因为set是支持删除和二分查找的
到了一个r,从栈顶开始找,如果栈顶永远比sufr大就退出,否则找到st[top]开始比r小的位置,标记一下到这个位置时就删除st[top],并且如果r被删除了st[top]也要删除哦!(因为r小st[top]一定小,因为小的是lcp部分)
所以用两个邻接链表h和hd表示(这一步好神啊),到位置r用dfs删除r位置需要删除的
 
对于询问按右端点排序,和上道题一样可以使用链表的方法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
using namespace std;
const int N=1e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,Q,l,r;
char s[N];
struct edge{
int v,ne;
}e[N],ed[N];
int cnt,h[N],hd[N],cntd;
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
}
inline void insd(int u,int v){
int &cnt=cntd,*h=hd;edge *e=ed;
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
}
struct ques{
int l,id,ne;
}q[N];
int cntq,hq[N];
inline void insq(int r,int l,int id){
int &cnt=cntq,*h=hq;
cnt++;
q[cnt].l=l;q[cnt].ne=h[r];h[r]=cnt;
q[cnt].id=id;
} int sa[N],rnk[N],t1[N],t2[N],height[N],c[N];
bool cmp(int *r,int a,int b,int j){
return a+j<=n&&b+j<=n&&r[a]==r[b]&&r[a+j]==r[b+j];
}
void getSA(int m){
int *r=t1,*k=t2;
for(int i=;i<=n;i++) c[r[i]=s[i]]++;
for(int i=;i<=m;i++) c[i]+=c[i-];
for(int i=n;i>=;i--) sa[c[r[i]]--]=i;
for(int j=;j<=n;j<<=){
int p=;
for(int i=n-j+;i<=n;i++) k[++p]=i;
for(int i=;i<=n;i++) if(sa[i]>j) k[++p]=sa[i]-j; for(int i=;i<=m;i++) c[i]=;
for(int i=;i<=n;i++) c[r[k[i]]]++;
for(int i=;i<=m;i++) c[i]+=c[i-];
for(int i=n;i>=;i--) sa[c[r[k[i]]]--]=k[i]; swap(r,k);p=;r[sa[]]=++p;
for(int i=;i<=n;i++) r[sa[i]]=cmp(k,sa[i],sa[i-],j)?p:++p;
if(p>=n) break;m=p;
}
}
void getHeight(){
for(int i=;i<=n;i++) rnk[sa[i]]=i;
int k=;
for(int i=;i<=n;i++){
if(k) k--;
if(rnk[i]==) continue;
int j=sa[rnk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
height[rnk[i]]=k;
}
}
int Log[N],Pow[],mn[N][];
void iniST(){
Pow[]=;for(int i=;i<;i++)Pow[i]=Pow[i-]<<;
Log[]=-;for(int i=;i<=n;i++)Log[i]=Log[i/]+;
}
void getST(int mn[N][],int a[]){
for(int i=;i<=n;i++) mn[i][]=a[i];
for(int j=;j<=Log[n];j++)
for(int i=;i+Pow[j]-<=n;i++)
mn[i][j]=min(mn[i][j-],mn[i+Pow[j-]][j-]);
}
int lcp(int x,int y){
x=rnk[x];y=rnk[y];
if(x>y) swap(x,y);x++;
int t=Log[y-x+];
return min(mn[x][t],mn[y-Pow[t]+][t]);
} int vis[N];
set<int> S;
void dfs(int u){//printf("dfs %d\n",u);
vis[u]=;S.erase(u);
for(int i=hd[u];i;i=ed[i].ne)
if(!vis[ed[i].v]) dfs(ed[i].v);
} int st[N],top,ans[N];
void solve(){
for(int r=;r<=n;r++){
S.insert(r);
while(top){
int len=lcp(r,st[top]);
if(s[st[top]+len]>s[r+len]) break;
ins(r+len,st[top]);insd(r,st[top]);top--;
}
st[++top]=r;
for(int i=h[r];i;i=e[i].ne)
if(!vis[e[i].v]) dfs(e[i].v);
for(int i=hq[r];i;i=q[i].ne)
ans[q[i].id]=*S.lower_bound(q[i].l);
}
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%s",s+);
n=strlen(s+);
getSA();getHeight();iniST();getST(mn,height);
Q=read();
for(int i=;i<=Q;i++) l=read(),r=read(),insq(r,l,i);
solve();
for(int i=;i<=Q;i++) printf("%d\n",ans[i]);
}
 
 
 

BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]的更多相关文章

  1. bzoj千题计划313:bzoj3879: SvT(后缀数组+st表+单调栈)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3879 把所有的后缀取出,按rank排序 求出相邻两个后缀的lcp 每个后缀对答案的贡献就是 与在它 ...

  2. bzoj千题计划314:bzoj3238: [Ahoi2013]差异(后缀数组+st表+单调栈)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3238 跟 bzoj3879 差不多 #include<cstdio> #include ...

  3. SPOJ 687 Repeats(后缀数组+ST表)

    [题目链接] http://www.spoj.com/problems/REPEATS/en/ [题目大意] 求重复次数最多的连续重复子串的长度. [题解] 考虑错位匹配,设重复部分长度为l,记s[i ...

  4. POJ 3693 Maximum repetition substring(后缀数组+ST表)

    [题目链接] poj.org/problem?id=3693 [题目大意] 求一个串重复次数最多的连续重复子串并输出,要求字典序最小. [题解] 考虑错位匹配,设重复部分长度为l,记s[i]和s[i+ ...

  5. BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay

    BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...

  6. UVA10829 L-Gap Substrings(后缀数组+ST表)

    后缀数组+ST表. 代填的坑. \(Code\ Below:\) #include <bits/stdc++.h> #define ll long long using namespace ...

  7. 【bzoj3879】SvT 后缀数组+倍增RMQ+单调栈

    题目描述 (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示), ...

  8. BZOJ.4453.cys就是要拿英魂!(后缀数组 单调栈)

    BZOJ 求字典序最大,容易想到对原串建后缀数组求\(rk\). 假设当前区间是\([l,r]\),对于在\([l,r]\)中的两个后缀\(i,j\)(\(i<j\)),显然我们不能直接比较\( ...

  9. bzoj 4453 cys就是要拿英魂! —— 后缀数组+单调栈+set

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4453 这种问题...一般先把询问离线,排序: 区间对后缀排名的影响在于一些排名大而位置靠后的 ...

随机推荐

  1. boosting、adaboost

    1.boosting Boosting方法是一种用来提高弱分类算法准确度的方法,这种方法通过构造一个预测函数系列,然后以一定的方式将他们组合成一个预测函数.他是一种框架算法,主要是通过对样本集的操作获 ...

  2. 从I/O复用谈epoll为什么高效

    上一篇文章中,谈了一些网络编程的基本概念.在现实使用中,用的最多的就是I/O复用了,无非就是select,poll,epoll 很多人提到网络就说epoll,认为epoll效率是最高的.单纯的这么认为 ...

  3. AngularJs之九(ending......)

    今天继续angularJs,但也是最后一篇关于它的了,基础部分差不多也就这些,后续有机会再写它的提升部分. 今天要写的也是一个基础的选择列表: 一:使用ng-options,数组进行循环. <d ...

  4. Ubuntu 14.04中Elasticsearch集群配置

    Ubuntu 14.04中Elasticsearch集群配置 前言:本文可用于elasticsearch集群搭建参考.细分为elasticsearch.yml配置和系统配置 达到的目的:各台机器配置成 ...

  5. System.FormatException: GUID 应包含带 4 个短划线的 32 位数(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。

    在NHibernate数据库查询中出现了这个错误,由于是数据库是mysql的,当定义的字段为char(36)的时候就会出现这个错误. [解决方法] 将char(36) 改成varchar(40)就行了 ...

  6. Android-armebi-v7a、arm64-v8a、armebi的坑

    先来一波扫盲: armeabi:针对普通的或旧的arm v5 cpu armeabi-v7a:针对有浮点运算或高级扩展功能的arm v7 cpu(32位ARM设备) arm64-v8a:64位ARM设 ...

  7. CSS 特殊属性介绍之 pointer-events

    首先看一下 MDN 上关于 pointer-events 的介绍: CSS属性 pointer-events 允许作者控制特定的图形元素在何时成为鼠标事件的 target.当未指定该属性时,SVG 内 ...

  8. WebGIS项目中利用mysql控制点库进行千万条数据坐标转换时的分表分区优化方案

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 项目中有1000万条历史案卷,为某地方坐标系数据,我们的真实 ...

  9. Android SDK 在线更新镜像服务器资源

    本文转自:http://blog.kuoruan.com/24.html.感谢原作者. 什么是Android SDK SDK:(software development kit)软件开发工具包.被软件 ...

  10. 关键帧动画:@keyframes

    关键帧动画:@keyframes: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...