CodeForces - 1037H: Security(SAM+线段树合并)
题意:给定字符串S; Q次询问,每次询问给出(L,R,T),让你在S[L,R]里面找一个字典序最小的子串,其字典序比T大。 没有则输出-1;
思路:比T字典序大,而且要求字典最小,显然就是在T的尾巴加一个很小的字符,如果不存在,则依次删去尾巴,直到“存在”。
而“存在”是指,前缀lim+一个字符‘x’后存在于[L+lim,R]中, 所以我们需要预处理出所有点的endpos,这个用线段树合并就可以了。
注意这里是每一个节点都要记录,所以和普通的启发式合并不太一样,这里需要每次新开一个节点。
#include<bits/stdc++.h>
#define rep2(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
char c[maxn]; int rt[maxn],N,tot;
struct in{
int L,R,sum;
}s[maxn*];
void ins(int &now,int L,int R,int p)
{
if(!now) now=++tot; s[now].sum++;
if(L==R) return ; int Mid=(L+R)>>;
if(p<=Mid) ins(s[now].L,L,Mid,p);
else ins(s[now].R,Mid+,R,p);
}
int merge(int x,int y)
{
if(!x||!y) return x|y;
int now=++tot;
s[now].L=merge(s[x].L,s[y].L);
s[now].R=merge(s[x].R,s[y].R);
s[now].sum=s[s[now].L].sum+s[s[now].R].sum;
return now;
}
bool query(int Now,int L,int R,int l,int r)
{
if(!Now||l>r) return false;
if(l<=L&&r>=R) return s[Now].sum;
int Mid=(L+R)>>;
if(l<=Mid&&query(s[Now].L,L,Mid,l,r)) return true;
if(r>Mid) return query(s[Now].R,Mid+,R,l,r);
return 0;
}
struct SAM{
int ch[maxn][],fa[maxn],maxlen[maxn],cnt,last;
int a[maxn],b[maxn];
void init()
{
cnt=last=;
memset(ch[],,sizeof(ch[]));
}
int add(int x,int id)
{
int np=++cnt,p=last; last=np;
ins(rt[np],,N,id);
maxlen[np]=maxlen[p]+; memset(ch[np],,sizeof(ch[np]));
while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
if(!p) fa[np]=;
else {
int q=ch[p][x];
if(maxlen[q]==maxlen[p]+) fa[np]=q;
else {
int nq=++cnt; maxlen[nq]=maxlen[p]+;
fa[nq]=fa[q]; fa[q]=fa[np]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
}
}
}
void sort()
{
rep(i,,cnt) a[i]=;
rep(i,,cnt) a[maxlen[i]]++;
rep(i,,cnt) a[i]+=a[i-];
rep(i,,cnt) b[a[maxlen[i]]--]=i;
for(int i=cnt;i>=;i--) {
int x=b[i];
if(fa[x]) rt[fa[x]]=merge(rt[fa[x]],rt[x]);
}
}
}T;
int pos[maxn],Q;
void solve()
{
int L,R,len,fcy;
scanf("%d%d%s",&L,&R,c+);
len=strlen(c+);
int now=,lim=len; c[len+]='a'-;
rep(i,,len) {
if(T.ch[now][c[i]-'a']) now=T.ch[now][c[i]-'a'];
else { lim=i-; break;}
pos[i]=now;
}
fcy=-; pos[]=;
for(int i=lim;i>=&&fcy==-;i--){
for(int j=c[i+]-'a'+;j<;j++){
int v=T.ch[pos[i]][j];
if(!v) continue;
if(query(rt[v],,N,L+i,R)) {
fcy=i+; c[fcy]='a'+j;
break;
}
}
}
if(fcy==-) puts("-1");
else { rep(i,,fcy) putchar(c[i]); puts(""); }
}
int main()
{
T.init();
scanf("%s",c+); N=strlen(c+);
rep(i,,N) T.add(c[i]-'a',i);
T.sort();
scanf("%d",&Q);
while(Q--) solve();
return ;
}
CodeForces - 1037H: Security(SAM+线段树合并)的更多相关文章
- CF1037H Security——SAM+线段树合并
又是一道\(SAM\)维护\(endpos\)集合的题,我直接把CF700E的板子粘过来了QwQ 思路 如果我们有\([l,r]\)对应的\(SAM\),只需要在上面贪心就可以了.因为要求的是字典序比 ...
- 【Codeforces 1037H】Security(SAM & 线段树合并)
Description 给出一个字符串 \(S\). 给出 \(Q\) 个操作,给出 \(L, R, T\),求字典序最小的 \(S_1\),使得 \(S^\prime\) 为\(S[L..R]\) ...
- Codeforces 1276F - Asterisk Substrings(SAM+线段树合并+虚树)
Codeforces 题面传送门 & 洛谷题面传送门 SAM hot tea %%%%%%% 首先我们显然可以将所有能够得到的字符串分成六类:\(\varnothing,\text{*},s, ...
- Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任 ...
- 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree
原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...
- UOJ#395. 【NOI2018】你的名字 字符串,SAM,线段树合并
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ395.html 题解 记得同步赛的时候这题我爆0了,最暴力的暴力都没调出来. 首先我们看看 68 分怎么做 ...
- loj#2059. 「TJOI / HEOI2016」字符串 sam+线段树合并+倍增
题意:给你一个子串,m次询问,每次给你abcd,问你子串sa-b的所有子串和子串sc-d的最长公共前缀是多长 题解:首先要求两个子串的最长公共前缀就是把反过来插入变成最长公共后缀,两个节点在paren ...
- 2019.02.27 bzoj4556: [Tjoi2016&Heoi2016]字符串(二分答案+sam+线段树合并)
传送门 题意:给一个字符串SSS. 有mmm次询问,每次给四个参数a,b,c,da,b,c,da,b,c,d,问s[a...b]s[a...b]s[a...b]的所有子串和s[x...y]s[x... ...
- CF700E:Cool Slogans(SAM,线段树合并)
Description 给你一个字符串,如果一个串包含两个可有交集的相同子串,那么这个串的价值就是子串的价值+1.问你给定字符串的最大价值子串的价值. Input 第一行读入字符串长度$n$,第二行是 ...
随机推荐
- 记一次网络故障——pod间无法通信
一.背景 集群是二进制部署 部署完成后一起正常,各种资源对象均可正常创建. 部署应用后发现无法跨节点通信,且pod的ip都是172.17.0.0段的 二.排查过程层 查看节点路由,发现docker0网 ...
- k8s+Jenkins+GitLab-自动化部署项目
0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 k8s架构目录:Kubernetes(k8s)集群部署(k8s企业级Docker容器集群管理)系列目录 此文阅读目录: 1.闲聊 ...
- BitSet源码
public class BitSet1 implements Cloneable, java.io.Serializable { // >>>左边补0, << 右边补0 ...
- mysql explain亲测
mysql explain亲测 1 where后面字段加索引:数据库类型如果是字符串类型 查询where的时候必须要用 字符串 类型必须一致 否则不用索引 type还是会是all的 ps:如果wher ...
- 网络基础 ----------- osi 与 一些协议
1.了解 OSI ISO IOS ISO(全称:International Organization for Standardization) 国际标准化组织, 成立于1947年2月23日,制定全世界 ...
- Linux学习笔记之RAID笔记
RAID: Redundant Arrays of Inexpensive Disks Independent Berkeley: A case for Redundent Arrays of Ine ...
- String类的方法应用
String类的几个方法的应用示例: using System;using System.Collections.Generic;using System.Linq;using System.Text ...
- xml文件操作帮助类
xml文件的节点值获取和节点值设置 /// <summary> /// 保存单个点节点的值 /// </summary> /// <param name="Up ...
- BZOJ3209: 花神的数论题(数位DP)
题目: 3209: 花神的数论题 解析: 二进制的数位DP 因为\([1,n]\)中每一个数对应的二进制数是唯一的,我们枚举\(1\)的个数\(k\),计算有多少个数的二进制中有\(k\)个\(1\) ...
- JDK 监控和故障处理工具
JDK 监控和故障处理工具 JDK 命令行工具 这些命令在 JDK 安装目录下的 bin 目录下: jps (JVM Process Status): 类似 UNIX 的 ps 命令.用户查看所有 J ...