\(>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. 网络流入门--最大流算法Dicnic 算法

    感谢WHD的大力支持 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2,3,4},有向管道{A,B,C,D,E},即有向图一张.  ...

  2. JS中函数void()

    <a href="javascript:void(0)">hello</a>/* * JS中函数void()的运用大体是这种新式; * void()是运算符 ...

  3. Python3 断言

    #!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:CarsonLi ''' 断言一般用于后面有非常重要的操作,需要使用前面的数据,而且不容许出 ...

  4. PXC加入新节点避免SST时grastate.dat文件内容的修改问题

    PXC加入新节点避免SST时grastate.dat文件内容的修改问题 在主从同步完成并关闭实例后,需要修改grastate.dat中的seqno:到底应该填已经执行过最后的XID号(Executed ...

  5. MySQL5.6 新特性之GTID【转】

    转自 MySQL5.6 新特性之GTID - jyzhou - 博客园http://www.cnblogs.com/zhoujinyi/p/4717951.html 背景: MySQL5.6在5.5的 ...

  6. 自动化运维工具SaltStack详细部署【转】

    ==========================================================================================一.基础介绍==== ...

  7. SYN Flood攻击及防御方法 (转)

    原文连接:http://blog.csdn.net/bill_lee_sh_cn/article/details/6065704 一.为什么Syn Flood会造成危害      这要从操作系统的TC ...

  8. python进行des加密解密,而且可以与JAVA进行互相加密解密

    import binasciifrom pyDes import des, CBC, PAD_PKCS5import uuidimport time # pip install -i https:// ...

  9. AC日记——#2054. 「TJOI / HEOI2016」树

    #2054. 「TJOI / HEOI2016」树 思路: 线段树: 代码: #include <cstdio> #include <cstring> #include < ...

  10. 使用Unity解耦你的系统—PART3——依赖注入

    继续学习Unity,在前几篇中已经将Unity的使用方法做了一个还算详细的介绍了,主要是如何通过代码及配置文件来注册对象之间的关系.Unity内置所有的生命周期管理使用介绍,及Unity的Regist ...