传送门

好题!!!
介于是一道权限题所以我就粘题面吧···

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|

一开始看到题的时候推了推性质(还有这种题询问这么多不是数据结构维护就是离线要么就是二分,显然不能数据结构也不能二分,所以只能是离线了)

对于两个后缀i,j(i&lt;j)i,j(i&lt;j)i,j(i<j):
若rk[i]&gt;rk[j]rk[i]&gt;rk[j]rk[i]>rk[j],不用管。
若rk[i]&lt;rk[j]rk[i]&lt;rk[j]rk[i]<rk[j],那么对于一些询问的RRR,若R≤j+lcp(i,j)−1R\le j+lcp(i,j)-1R≤j+lcp(i,j)−1,这个时候应该是rk[i]rk[i]rk[i]要更大些,因为后面的字母会被截断,若R&gt;j+lcp(i,j)−1R&gt;j+lcp(i,j)-1R>j+lcp(i,j)−1,就是rk[j]rk[j]rk[j]更大。

所以我们一定是离线之后往过扫,一边修改,一定是给j+lcp(i,j)j+lcp(i,j)j+lcp(i,j)的地方打个标记什么的,但想到这我就不会了

其实就是一个很神奇的操作

用单调栈优化setsetset,简单来说就是维护了两种边,一种是伴随边,一种是删除边,当r+1r+1r+1的时候,要把r+1r+1r+1处的删除边连的点都删掉,然后把删掉的点的伴随点也删掉,然后答案就是setsetset里面LLL的后继

因为后缀排序写错wawawa了半天,还有lcplcplcp那里是用rankrankrank来求的

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#define maxn 200005
#define LL long long
using namespace std;inline int rd(){int x=0,f=1;char c=getchar();while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();return x*f;
}int n,m,q,tax[maxn],sa[maxn],rk[maxn],tp[maxn],h[maxn],st[maxn][20],ans[maxn];
int stk[maxn],top;
char s[maxn];
set<int> ss;inline void rsort(){for(int i=1;i<=m;i++) tax[i]=0;for(int i=1;i<=n;i++) tax[rk[i]]++;for(int i=1;i<=m;i++) tax[i]+=tax[i-1];for(int i=n;i;i--) sa[tax[rk[tp[i]]]--]=tp[i];
}inline void ssort(){for(int i=1;i<=n;i++) rk[i]=s[i],tp[i]=i;rsort();for(int w=1,p=0;w<=n&&p<n;w<<=1,m=p){p=0;for(int i=n-w+1;i<=n;i++) tp[++p]=i;for(int i=1;i<=n;i++)if(sa[i]>w) tp[++p]=sa[i]-w;rsort(); swap(rk,tp);rk[sa[1]]=p=1;for(int i=2;i<=n;i++)if(tp[sa[i]]==tp[sa[i-1]]&&tp[min(n+1,sa[i]+w)]==tp[min(n+1,sa[i-1]+w)])rk[sa[i]]=p;else rk[sa[i]]=++p;}
}inline void get_h(){int j,k=0;for(int i=1;i<=n;i++){if(k) --k;j=sa[rk[i]-1];while(s[j+k]==s[i+k]) ++k;h[rk[i]]=k;}
}inline void prework(){for(int i=1;i<=n;i++) st[i][0]=h[i];for(int j=1;(1<<j)<=n;j++)for(int i=1;i+(1<<j)-1<=n;i++)//i写成j了我手残 QAQ st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}inline int lcp(int l,int r){l=rk[l],r=rk[r];//!!!if(l>r) swap(l,r); ++l;int k=log2(r-l+1); return min(st[l][k],st[r-(1<<k)+1][k]);
}struct Que{int l,r,id;bool operator <(const Que &x) const{return r<x.r;}
}qu[maxn];int to[maxn],nxt[maxn],head1[maxn],head2[maxn],cnt;//head1 with head2 delete
bool del[maxn];void dfs(int x){del[x]=1; ss.erase(x);for(int i=head1[x];i;i=nxt[i])if(!del[to[i]]) dfs(to[i]);
}inline void add(int ty,int x,int y){if(x>n) return;if(ty) to[++cnt]=y,nxt[cnt]=head1[x],head1[x]=cnt;else to[++cnt]=y,nxt[cnt]=head2[x],head2[x]=cnt;
}int main(){scanf("%s",s+1); n=strlen(s+1); m=127;ssort(); get_h(); prework();q=rd();for(int i=1;i<=q;i++) qu[i].l=rd(),qu[i].r=rd(),qu[i].id=i;sort(qu+1,qu+1+q);int now=1;for(int i=1;i<=q;i++){while(now<=qu[i].r){while(top && rk[stk[top]]<rk[now]){add(0,now+lcp(now,stk[top]),stk[top]),add(1,now,stk[top]);top--;}stk[++top]=now; ss.insert(now);for(int j=head2[now];j;j=nxt[j]) if(!del[to[j]]) dfs(to[j]);++now;}ans[qu[i].id]=*(ss.lower_bound(qu[i].l));}for(int i=1;i<=q;i++) printf("%d\n",ans[i]);return 0;
}

后缀数组+单调栈+set--bzoj4453: cys就是要拿英魂!相关推荐

  1. [Ahoi2013]差异[后缀数组+单调栈]

    链接 解题思路:很明显前面∑1<=i<j<=nlen(Ti)+len(Tj)\sum_{1<=i<j<=n}len(T_i)+len(T_j)∑1<=i< ...

  2. [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】

    题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...

  3. BZOJ3879: SvT【后缀数组+单调栈】

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

  4. POJ - 3415 Common Substrings(后缀数组+单调栈)

    题目链接:点击查看 题目大意:给出两个字符串,再给出一个k,问两个字符串中长度大于等于k的公共子串有多少个(种类可重复) 题目分析:因为涉及到了子串问题,先用后缀数组跑出height数组来,接下来如果 ...

  5. [bzoj3238]差异(后缀数组+单调栈)

    显然我们可以先把len(Ti)+len(Tj)的值先算出来,再把LCP减去.所有len(Ti)+len(Tj)的值为n*(n-1)*(n+1)/2,这个随便在纸上画一画就可以算出来的. 接下来问题就是 ...

  6. [BZOJ3238][AHOI2013]差异 [后缀数组+单调栈]

    题目地址 - GO-> 题目大意: 给定一个长度为 nn 的字符串SS,令TiTi表示它从第ii个字符开始的后缀,求以下这个式子的值: ∑1≤i<j≤nlen(Ti)+len(Tj)−2× ...

  7. 【BZOJ3879】SvT,后缀数组+单调栈维护sum

    Time:2016.08.15 Author:xiaoyimi 转载注明出处谢谢 如果有不明白的地方可以在下面评论问我 传送门 思路: 建立后缀数组求出Height 如果说对每次询问暴力求LCP累加的 ...

  8. POJ 3415 后缀数组+单调栈

    题目大意: 给定A,B两种字符串,问他们当中的长度大于k的公共子串的个数有多少个 这道题目本身理解不难,将两个字符串合并后求出它的后缀数组 然后利用后缀数组求解答案 这里一开始看题解说要用栈的思想,觉 ...

  9. bzoj 3238: [Ahoi2013]差异(后缀数组+单调栈)

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 3443  Solved: 1562 [Submit][Stat ...

  10. 【HAOI2016/BZOJ4566】找相同字符 后缀数组+单调栈

    原题走这里 鉴于我实在不是很懂单调栈和单调队列这一系列东西,所以我决定稍微具体讲一下单调栈. 恩,本题实质上就是求两个字符串的公共子串数,其中只要出现位置不同,就算是不同的子串. 处理多个字符串的经典 ...

最新文章

  1. 没人比程序猿更讨厌软件
  2. 关于使用jQuery时$(document).ready()方法失效问题
  3. js实现点击自动下载文件
  4. .NET(c#) 移动APP开发平台 - Smobiler(1)
  5. 【OC底层】OC对象本质,如 isa, super-class
  6. The Double-Checked Locking is Broken Declaration
  7. [转]OOPC:Object-Oriented Programming in C
  8. 雷林鹏分享:jQuery EasyUI 数据网格 - 自定义排序
  9. 算法导论--最小生成树(Kruskal和Prim算法)
  10. 基于3D人像复原技术的试衣平台
  11. echarts-python数据可视化大屏展示
  12. 【自然语言处理】【实体匹配】PromptEM:用于低资源广义实体匹配的Prompt-tuning
  13. redis主从配置及主从切换
  14. Python 中文分词 NLPIR 快速搭建
  15. java 计算体积_java 求体积
  16. 要你命三千又三千的成长之旅
  17. 4.17记录 LIS其二
  18. CANoe.DiVa操作指南——基于DoIP使用CANoe.DiVa用于UDS一致性测试
  19. NFT Insider #87:The Sandbox 收购游戏开发工作室 Sviper,GHST 大迁徙即将拉开帷幕
  20. Android Studio代码检查lint使用

热门文章

  1. 阿里云mysql空间不足_阿里云数据库MySQL系统文件导致实例空间满的解决办法
  2. 十四、数字图像处理之图像压缩
  3. gentoo 安装笔记
  4. 浏览器下载文件时文件名中文乱码问题
  5. 12306怎样才能防止抢票?
  6. Django | ORM choices参数详解
  7. 看小伙如何跟反爬抗争到底
  8. C语言发展史——程序猿抗争史
  9. python 全栈开发是什么意思_我为什么说Python是全栈式开发语言?
  10. 在系统中增加各银行卡刷卡消费分析