• [CF1037H] Security


    题目链接

    codeforces.

    洛谷.

    Solution

    按照套路,可以(SAM)上线段树合并求出(endpos)集合,然后随便贪心一下就好了。

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    #define mid ((l+r)>>1)
    
    const int maxn = 4e5+10;
    const int inf = 1e9;
    const lf eps = 1e-8;
    
    int rt[maxn];
    
    namespace sgt {  //segment tree
    	int tot,ls[maxn*20],rs[maxn*20];
    
    	void insert(int &p,int l,int r,int x) {
    		if(!p) p=++tot;
    		if(l==r) return ;
    		if(x<=mid) insert(ls[p],l,mid,x);
    		else insert(rs[p],mid+1,r,x);
    	}
    	
    	int query(int p,int l,int r,int x,int y) {
    		if((!p)||x>y) return 0;
    		if(x<=l&&r<=y) return 1;
    		int res=0;
    		if(x<=mid) res|=query(ls[p],l,mid,x,y);
    		if(y>mid) res|=query(rs[p],mid+1,r,x,y);
    		return res;
    	}
    	
    	int merge(int x,int y) {
    		if(!x||!y) return x^y;
    		int now=++tot;
    		ls[now]=merge(ls[x],ls[y]);
    		rs[now]=merge(rs[x],rs[y]);
    		return now;
    	}
    }
    
    int n,q;
    char s[maxn];
    
    namespace sam { //suffix automaton
    	int tr[maxn][26],par[maxn],ml[maxn],cnt=1,lstp=1,pos[maxn];
    	void append(int x) {
    		int p=lstp,np=++cnt;ml[np]=ml[p]+1;lstp=np;
    		sgt::insert(rt[np],1,n,ml[np]);
    		for(;p&&tr[p][x]==0;p=par[p]) tr[p][x]=np;
    		if(!p) return par[np]=1,void();
    		int q=tr[p][x];
    		if(ml[p]+1<ml[q]) {
    			int nq=++cnt;ml[nq]=ml[p]+1;
    			memcpy(tr[nq],tr[q],sizeof tr[nq]);
    			par[nq]=par[q],par[q]=par[np]=nq;
    			for(;p&&tr[p][x]==q;p=par[p]) tr[p][x]=nq;
    		} else par[np]=q;
    	}
    
    	struct Tree {
    		int head[maxn],tot;
    		struct edge{int to,nxt;}e[maxn<<1];
    		void ins(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
    		void dfs(int x) {
    			for(int i=head[x];i;i=e[i].nxt)
    				dfs(e[i].to),rt[x]=sgt::merge(rt[x],rt[e[i].to]);
    		}
    	}T;
    	
    	void prepare() {for(int i=2;i<=cnt;i++) T.ins(par[i],i);T.dfs(1);}
    	
    	void solve() {
    		int l,r;read(l),read(r);scanf("%s",s+1);
    		int len=strlen(s+1),now=1,lim=len;pos[0]=1;
    		for(int i=1,v;i<=len;i++)
    			if(tr[now][v=s[i]-'a']) now=tr[now][v],pos[i]=now;
    			else {lim=i-1;break;}
    		int bo=0;
    		for(int i=lim;~i;i--) {
    			for(int j=(i==len?0:s[i+1]-'a'+1);j<26;j++)
    				if(sgt::query(rt[tr[pos[i]][j]],1,n,l+i,r)) {
    					for(int k=1;k<=i;k++) putchar(s[k]);
    					putchar(j+'a'),puts(""),bo=1;goto end;
    				}
    		}end:;
    		if(!bo) puts("-1");
    	}
    }
    
    int main() {
    	scanf("%s",s+1);n=strlen(s+1);
    	for(int i=1;i<=n;i++) sam:: append(s[i]-'a');
    	sam:: prepare();read(q);while(q--) sam::solve();
    	return 0;
    }
    
  • 相关阅读:
    makedown
    前端
    关于阅读与自我认同
    Win10任务栏透明工具 TranslucentTB
    Linux文件属性
    解决vscode出现两个光标的问题
    一文搞懂vim复制粘贴
    解决vim选中文字不能复制的问题
    简单配置让iterm2用得更爽
    区块链相关在线加解密工具(非对称加密/hash)
  • 原文地址:https://www.cnblogs.com/hbyer/p/10594574.html
Copyright © 2020-2023  润新知