\(>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. form表单设置input文本属性只读,不可更改

    记住一条好用的,设置readonly属性为true <input     readonly=''true"> 更多方法,转载: http://www.jb51.net/web/6 ...

  2. 2017ACM暑期多校联合训练 - Team 7 1002 HDU 6121 Build a tree (深搜+思维)

    题目链接 Problem Description HazelFan wants to build a rooted tree. The tree has n nodes labeled 0 to n− ...

  3. WordPress手机端插件——WPtouch

    戒微博之后,把更多的精力开始转投回网站上来:今天用nexus7访问@Bee君 的博客时,发现博客的界面与电脑上访问的界面不相同,顺藤摸瓜之后发现原来bee君使用的是WPtouch-pro插件来实现移动 ...

  4. 安装node-sass的正确姿势【转】

    安装 node-sass 的时候总是会各种不成功,今天我琢磨了一会儿总算知道要怎么解决了. 首先要知道的是,安装 node-sass 时在 node scripts/install 阶段会从 gith ...

  5. 残差网络(Residual Network)

    一.背景 1)梯度消失问题 我们发现很深的网络层,由于参数初始化一般更靠近0,这样在训练的过程中更新浅层网络的参数时,很容易随着网络的深入而导致梯度消失,浅层的参数无法更新. 可以看到,假设现在需要更 ...

  6. Linux内核中的Cache段

    Linux内核中的Cache段 原文地址:http://blogold.chinaunix.net/u2/85263/showart_1743693.html 最近移植LEON3的内核时,了解了一些简 ...

  7. js日期工具

    /** * 日期工具类 */ define(function(require, exports, module) { var constants = require("constants&q ...

  8. ubuntu查看mysql版本的几种方法

    ubuntu查看mysql版本的几种方法 mysql 1:在终端下:mysql -V(大写) //代码 $ mysql -V mysql Ver 14.14 Distrib 5.5.46, for d ...

  9. linux的fwrite()使用方法,当前时间写入文本的程序

    fwrite函数 1.函数功能 用来读写一个数据块. 2.一般调用形式 fwrite(buffer,size,count,fp); 3.说明 (1)buffer:是一个指针,对fread来说,它是读入 ...

  10. (三)Spring 之AOP 详解

    第一节:AOP 简介 AOP 简介:百度百科: 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个 ...