zoukankan      html  css  js  c++  java
  • Codeforces 1037 H. Security

    (>Codeforces space 1037 H. Security<)

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

    (1 leq |S|leq 10^5, 1leq q leq 2 imes 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('
    ');
    	}
    }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;
    }
    
    

  • 相关阅读:
    水晶报表参数字段在代码中赋值
    存储过程编写经验和优化措施
    积分与排名
    大话处理器
    抽象数学
    开普勒:天空的立法者
    Scalable Face Image Retrieval with IdentityBased Quantization and Multireference Reranking
    配色辞典
    图像识别顶级赛事
    Information Geometry
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9643649.html
Copyright © 2011-2022 走看看