\(>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. JSP和Servlet面试题

    1.讲下servlet的执行流程. Servlet的执行流程也就是servlet的生命周期,当服务器启动的时候生命周期开始,然后通过init()<启动顺序根据web.xml里的startup-o ...

  2. 爬虫实战--基于requests和beautifulsoup的妹子网图片爬取(福利哦!)

    #coding=utf-8 import requests from bs4 import BeautifulSoup import os all_url = 'http://www.mzitu.co ...

  3. Ice Cream Tower Gym - 101194D (贪心 + 二分 )

    题目链接 : https://cn.vjudge.net/problem/Gym-101194D 题目大意 : 给你n个冰激凌球,让你用这些冰激凌球去垒冰激凌,要求是下面的这一个必须是他上面一个的两倍 ...

  4. 4-Python数据类型之元组-字符串

    目录 1 元组概念 1.1 元祖的特点 1.2 元组的定义 1.3 元组的访问 1.4 元组的查询 2 命名元组 3 字符串 3.1 字符串的基本操作 3.1.1 字符串的访问 3.1.2 字符串的拼 ...

  5. C++学习之路(十):虚继承引入的执行效率

    这篇文章不知道取啥名字了,暂且这样叫,直接看场景就明白了.节选自<深度探索C++对象模型> Point3d origin, *pt = &origin; (1)origin.x = ...

  6. NGUI优化之Drawcall

    今天在运行之前的程序时,无意中发现一个简单的menu菜单页面drawcall居然达到接近30了,这个数值感觉太高了. 后网上查询关于降低drawcall的方法,发现主要有以下几点: 1.少用Panel ...

  7. effective c++读书笔记(一)

    很早之前就听过这本书,找工作之前读一读.看了几页,个人感觉实在是生涩难懂,非常不符合中国人的思维方式.之前也有博主做过笔记,我来补充一些自己的理解. 我看有人记了笔记,还不错:http://www.3 ...

  8. sad 关于一些html5新属性还需要用https才能支持

    像我昨天在搞一个录音的小东西 在本地正常录音正常播放 但是放到线上环境http环境上就出现了如上的错误 功能都不能正常使用 然后就改成https线上环境  然后就正常了 如上 大家有什么赐教的欢迎留言 ...

  9. 湖南省第六届省赛题 Biggest Number (dfs+bfs,好题)

    Biggest Number 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 You have a maze with obstacles and non-zero di ...

  10. CSU 1412 Line and Circles

    原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1412 题目要求判断是否有一条直线可以穿过所有的圆. 做法:把所有圆心做一次凸包,然后判断 ...