\(>Codeforces \space 1037\ H. Security<\)

题目大意 : 有一个串 \(S\) ,\(q\) 组询问,每一次给出一个询问串 \(T\) 和一个区间 \([l,r]\) ,要求找出 \(S\) 在 \([l,r]\) 之间的子串中字典序大于 \(T\) 且最小的

\(1 \leq |S|\leq 10^5, 1\leq q \leq 2 \times 10^5\)

解题思路 :

其实这个题一点意思都没有,就是一个 \(sam\) + 线段树合并裸题..

但是某位不得了的指导大人近期 \(AC\) 了此题,于是我就去顺手做了一下

考虑每次把询问串在 \(sam\) 上匹配,对于每一个在 \(sam\) 上出现的 \(T\) 的合法前缀,大力算出能否在后面加一个字符满足比 \(T\) 大且在 \(L, R\) 区间

后者线段树合并维护即可

/*program by mangoyang*/
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 1000005;
char s[N]; int n;
struct SegmentTree{
int sz[N*25], lc[N*25], rc[N*25], size;
inline void ins(int &u, int l, int r, int pos){
if(!u) u = ++size;
if(l == r) return (void) (sz[u]++);
int mid = l + r >> 1;
if(pos <= mid) ins(lc[u], l, mid, pos);
else ins(rc[u], mid + 1, r, pos); sz[u] = sz[lc[u]] + sz[rc[u]];
}
inline int merge(int x, int y, int l, int r){
if(!x || !y) return x + y;
int o = ++size, mid = l + r >> 1;
if(l == r) sz[o] = sz[x] + sz[y];
else{
lc[o] = merge(lc[x], lc[y], l, mid);
rc[o] = merge(rc[x], rc[y], mid + 1, r);
sz[o] = sz[lc[o]] + sz[rc[o]];
}
return o;
}
inline int query(int u, int l, int r, int L, int R){
if(!u || l > r) return 0;
if(l >= L && r <= R) return sz[u];
int mid = l + r >> 1, res = 0;
if(L <= mid) res += query(lc[u], l, mid, L, R);
if(mid < R) res += query(rc[u], mid + 1, r, L, R);
return res;
}
}Seg;
struct SaffixAutomaton{
vector<int> g[N];
int ch[N][26], dep[N], rt[N], fa[N], size, tail;
inline SaffixAutomaton(){ size = tail = 1; }
inline int newnode(int x){ return dep[++size] = x, size; }
inline void ins(int c, int pos){
int p = tail, np = newnode(dep[p] + 1);
Seg.ins(rt[np], 1, n, pos);
for(; !ch[p][c] && p; p = fa[p]) ch[p][c] = np;
if(!p) return (void) (fa[np] = 1, tail = np);
int q = ch[p][c];
if(dep[q] == dep[p] + 1) fa[np] = q;
else{
int nq = newnode(dep[p] + 1);
fa[nq] = fa[q], fa[q] = fa[np] = nq;
for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
for(; ch[p][c] == q && p; p = fa[p]) ch[p][c] = nq;
}tail = np;
}
inline void dfs(int u){
for(int i = 0; i < g[u].size(); i++){
int v = g[u][i];
dfs(v), rt[u] = Seg.merge(rt[u], rt[v], 1, n);
}
}
inline void Prework(){
for(int i = 1; i <= size; i++) g[fa[i]].push_back(i); dfs(1);
}
inline void solve(char *s, int l, int r){
int len = strlen(s + 1), p = 1, pos = 0, res = 0;
for(int i = 1; i <= len + 1; i++){
int c = i > len ? (-1) : (s[i] - 'a'), flg = 0;
for(int j = c + 1; j < 26; j++) if(ch[p][j]){
int u = ch[p][j];
if(Seg.query(rt[u], 1, n, l + i - 1, r)){
res = j + 'a', pos = i - 1; break;
}
}
if(ch[p][c]) p = ch[p][c]; else break;
}
if(!res) return (void) puts("-1");
for(int i = 1; i <= pos; i++) putchar(s[i]);
putchar(res), putchar('\n');
}
}van;
int main(){
scanf("%s", s + 1); n = strlen(s + 1);
for(int i = 1; i <= n; i++) van.ins(s[i] - 'a', i);
van.Prework(); int Q; read(Q);
for(int i = 1, l, r; i <= Q; i++)
read(l), read(r), scanf("%s", s + 1), van.solve(s, l, r);
return 0;
}

Codeforces 1037 H. Security的更多相关文章

  1. Codeforces 948D Perfect Security(字典树)

    题目链接:Perfect Security 题意:给出N个数代表密码,再给出N个数代表key.现在要将key组排序,使key组和密码组的亦或所形成的组字典序最小. 题解:要使密码组里面每个数都找到能使 ...

  2. codeforces 14A - Letter & codeforces 859B - Lazy Security Guard - [周赛水题]

    就像title说的,是昨天(2017/9/17)周赛的两道水题…… 题目链接:http://codeforces.com/problemset/problem/14/A time limit per ...

  3. CodeForces 923C Perfect Security

    C. Perfect Security time limit per test3.5 seconds memory limit per test512 megabytes inputstandard ...

  4. Codeforces 948D Perfect Security

    Perfect Security 题意:给你一个A[i]数组, 再给你一个B[i]数组, 现在用选取 B[i] 数组中的一个 去和 A[i] 数组里的一个元素去进行异或操作, B[i]数组的元素只能用 ...

  5. 【Codeforces 1037H】Security(SAM & 线段树合并)

    Description 给出一个字符串 \(S\). 给出 \(Q\) 个操作,给出 \(L, R, T\),求字典序最小的 \(S_1\),使得 \(S^\prime\) 为\(S[L..R]\) ...

  6. Codeforces Gym H. Hell on the Markets 贪心

    Problem H. Hell on the MarketsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vj ...

  7. codeforces 1037

    题解: E-trips 哎哎哎好傻逼啊 没有想到算不能的一直在想怎么算能的 太傻逼了 其实很简单 我们只需要对好友<=k的首先dfs一下给他连接着的朋友-1 然后如果小于了就递归下去 这个正确性 ...

  8. Codeforces 948D Perfect Security 【01字典树】

    <题目链接> 题目大意: 给定两个长度为n的序列,可以改变第二个序列中数的顺序,使得两个序列相同位置的数异或之后得到的新序列的字典序最小. 解题分析: 用01字典树来解决异或最值问题.因为 ...

  9. 2018.12.08 codeforces 948D. Perfect Security(01trie)

    传送门 01trie板子题. 给出两个数列,允许把第二个数列重新排列. 求使得两个数列每个位置对应的数的异或值和成为最小值的每个位置的异或和. 把第二个数列插入到01trie里面然后对于第一个数列中的 ...

随机推荐

  1. 【BZOJ】4358: permu 莫队算法

    [题意]给定长度为n的排列,m次询问区间[L,R]的最长连续值域.n<=50000. [算法]莫队算法 [题解]考虑莫队维护增加一个数的信息:设up[x]表示数值x往上延伸的最大长度,down[ ...

  2. iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址(2014年2月19日更新版)

    //转载请注明出处--本文永久链接:http://www.cnblogs.com/ChenYilong/p/3496069.html     编号 iOS-Apple苹果官方文档翻译名称 博文链接地址 ...

  3. Oozie与Coordinator调度讲解及系统时区配置与定时触发两种配置方式

    1:修改本地linux时区 查看时区 - 号代表西  + 号 代表东 北京时间是东八区 设置时区的配置文件所在位置 cd /usr/share/zoneinfo/ 选择以亚洲的上海 的时区为基址 删除 ...

  4. 模型稳定度指标PSI与IV

    由于模型是以特定时期的样本所开发的,此模型是否适用于开发样本之外的族群,必须经过稳定性测试才能得知.稳定度指标(population stability index ,PSI)可衡量测试样本及模型开发 ...

  5. 阿里Java研发工程师实习面经,附面试技巧

    作者:如何进阿里 链接:https://www.nowcoder.com/discuss/72899?type=0&order=0&pos=17&page=1 来源:牛客网 前 ...

  6. think php模板的使用

    {include file="../application/public/header.html"}<!-- Jumbotron --><div class=&q ...

  7. MySQL启动很慢的原因

    我们在启动MySQL的时候,常常会遇到的是, 当执行启动命令后,它会"Start MySQL ....." 一直不停的执行,也不中断,也不成功 这里会出现此现象的原因有以下三条: ...

  8. pyQt: eg3

    import sys import urllib2 from PyQt4 import QtCore from PyQt4 import QtGui class Form(QtGui.QDialog) ...

  9. sshpass-免交互SSH登录工具

    sshpass用于自动向命令行提供密码,适用于ssh,scp,rsync,pssh,pscp等ssh系列的命令和工具 #安装sshpass yum install sshpass -y #注:当第一次 ...

  10. Spring中的@Transactional事务注解

    事务注解方式 @Transactional 当标于类前时, 标示类中所有方法都进行事物处理 , 例子: @Transactional public class TestServiceBean impl ...