CF1037H Security 线段树合并 SAM
LINK:Security
求一个严格大于T的字符串 是原字符串S[L,R]的子串。
容易想到尽可能和T相同 然后再补一个尽可能小的字符即可。
出于这种思想 可以在SAM上先跑匹配 然后枚举加哪个字符 判定即可。
判定s是否在[L,R]中出现过 最快的方法 就是right集了。
这个可以线段树合并完成 注意 合并的时候 需要新建节点 防止把儿子的信息给改了。
倒着贪心即可。空间复杂度大概是nlog^2左右的注意开够。(我也不太会计算空间
const int MAXN=100010;
int n,m,id,len;
int last=1,cnt=1,top;
char a[MAXN<<1],b[MAXN<<1];
struct wy
{
int fa,len;
int ch[26];
}t[MAXN<<1];
int root[MAXN<<1],q[MAXN<<1],c[MAXN<<1],pre[MAXN<<1];
struct jl{int l,r,sum;}s[MAXN*200];
inline void insert(int x)
{
int p=last;
int np=last=++cnt;
len(np)=len(p)+1;
while(p&&!t[p].ch[x])
{
t[p].ch[x]=np;
p=f(p);
}
if(!p)f(np)=1;
else
{
int q=t[p].ch[x];
if(len(p)+1==len(q))f(np)=q;
else
{
int nq=++cnt;
t[nq]=t[q];
len(nq)=len(p)+1;
f(np)=f(q)=nq;
while(p&&t[p].ch[x]==q)
{
t[p].ch[x]=nq;
p=f(p);
}
}
}
}
inline void change(int &p,int l,int r,int x)
{
if(!p)p=++id;
if(l==r){++sum(p);return;}
int mid=(l+r)>>1;
if(x<=mid)change(l(p),l,mid,x);
else change(r(p),mid+1,r,x);
sum(p)=sum(l(p))+sum(r(p));
}
inline void topsort()
{
rep(1,cnt,i)++c[len(i)];
rep(1,cnt,i)c[i]+=c[i-1];
rep(1,cnt,i)q[c[len(i)]--]=i;
}
inline int merge(int x,int y,int l,int r)
{
if(!x||!y)return x|y;
int w=++id;
if(l==r){sum(w)=sum(x)+sum(y);return w;}
int mid=(l+r)>>1;
l(w)=merge(l(x),l(y),l,mid);
r(w)=merge(r(x),r(y),mid+1,r);
sum(w)=sum(l(w))+sum(r(w));
return w;
}
inline int ask(int p,int l,int r,int L,int R)
{
if(!p||L>R)return 0;
if(L<=l&&R>=r)return sum(p);
int mid=(l+r)>>1,ww=0;
if(L<=mid)ww+=ask(l(p),l,mid,L,R);
if(R>mid)ww+=ask(r(p),mid+1,r,L,R);
return ww;
}
int main()
{
freopen("1.in","r",stdin);
gc(a);len=strlen(a+1);
rep(1,len,i)insert(a[i]-'a'),change(root[last],1,len,i);
topsort();gt(n);
fep(cnt,2,i)root[f(q[i])]=merge(root[f(q[i])],root[q[i]],1,len);
rep(1,n,i)
{
int x,y;
gt(x);gt(y);gc(b);
int now=1,last=-1,flag=0;top=0;
int len1=strlen(b+1);
rep(1,len1,j)
{
int cc=b[j]-'a';
if(t[now].ch[cc])pre[t[now].ch[cc]]=now,now=t[now].ch[cc],a[++top]=b[j];
else {last=b[j]-'a';break;}
}
while(now)
{
rep(last+1,25,j)
{
if(flag)break;
int ww=t[now].ch[j];
if(ww)
{
if(ask(root[ww],1,len,x+top,y))
{
a[++top]=j+'a';
flag=1;
}
}
}
if(flag)break;
now=pre[now];last=b[top]-'a';
--top;
}
if(!flag){puts("-1");}
else {rep(1,top,i)printf("%c",a[i]);puts("");}
}
return 0;
}
CF1037H 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 - 1037H: Security(SAM+线段树合并)
题意:给定字符串S: Q次询问,每次询问给出(L,R,T),让你在S[L,R]里面找一个字典序最小的子串,其字典序比T大. 没有则输出-1: 思路:比T字典序大,而且要求字典最小,显然就是在T的尾巴 ...
- CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心
题目描述: 给定一个字符串 $S$ 给出 $Q$ 个操作,给出 $L,R,T$,求出字典序最小的 $S_{1}$ 为 $S[L...R]$的子串,且 $S_{1}$ 的字典序严格大于 $T$. 输出这 ...
- 洛谷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 分怎么做 ...
- Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任 ...
- 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... ...
随机推荐
- MRCTF 2020-“TiKi小组”
题目状态: OPEN - 正在试图解这道题CLOSED - 这道题还没有打开SOLVED - 解决了!鼓掌撒花! 赛事信息 Flag格式:MRCTF{}起止时间:2020-03-27 18:00:00 ...
- 日期推算:datetime
>>> import datetime >>> datetime.datetime.now() datetime.datetime(2020, 5, 20, 23, ...
- day38 作业
实现并发的里两种方式 # 第一种 from multiprocessing import Process import time class MyProcess(Process): def run(s ...
- day20 函数收尾+面向过程+模块
目录 一.算法(二分法) 二.面向过程与函数式 1 编程范式/思想 2 面向过程 3 函数式 3.1 匿名函数与lambda 三.模块 1 什么是模块 2 为何要有模块 3 怎么用模块 3.1第一次导 ...
- 浏览器如何解析css选择器?
浏览器会『从右往左』解析CSS选择器. 我们知道DOM Tree与Style Rules合成为 Render Tree,实际上是需要将Style Rules附着到DOM Tree上, 因此需要根据选择 ...
- HTTP协议——详细版
一 HTTP协议简介 作为学习前端开发的开始,我们必须搞明白以下几件事 1.什么是互联网 互联网=物理连接介质+互联网协议 2.互联网建立的目的? 数据传输打破地域限制,否则 ...
- node+express实现简单的增删改查
var express = require('express'); var bodyParser = require("body-parser"); var cors = requ ...
- JVM 专题十六:StringTable
1. String的基本特性 String:字符串,使用一对""引起来表示. String声明为final的,不可被继承. String实现了Serializable接口:表示字符 ...
- java 基本语法(三) 运算符
1-算术运算符 1.算术运算符: + - + - * / % (前)++ (后)++ (前)-- (后)-- + [典型代码] //除号:/ int num1 = 12; int num2 = 5; ...
- C# 接口与抽象类的区别? 情景下使用接口,什么情景下使用抽象类?
接口与抽象类的区别: 接口支持多继承:抽象类不能实现多继承. 接口可以用于支持回调:抽象类不能实现回调,因为继承不支持. 接口只包含方法.属性.索引器.事件的签名,但不能定义字段和包含实现的方法:抽象 ...