zoukankan      html  css  js  c++  java
  • CF1037H Security

    题意

    显然是贪心。

    先建出SAM,之后能走相同的字符就走相同的字符,实在不行再走一个比它大的。

    考虑怎么处理([l,r])的限制,我们只要用线段树合并维护出每个点的endpos集合,到时候判断下走这一步是否合法即可。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    int T,n,tot,cnt;
    int root[maxn],head[maxn];
    char s[maxn],t[maxn],ans[maxn];
    inline int read()
    {
    	char c=getchar();int res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f;
    }
    struct edge{int to,nxt;}e[maxn<<1];
    inline void add(int u,int v){e[++cnt].nxt=head[u];head[u]=cnt;e[cnt].to=v;}
    struct Seg
    {
    	#define lc(p) (seg[p].lc)
    	#define rc(p) (seg[p].rc)
    	#define sum(p) (seg[p].sum)
    	int lc,rc,sum;
    }seg[maxn*50];
    void insert(int &p,int l,int r,int pos)
    {
    	if(!p)p=++tot;
    	sum(p)++;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(pos<=mid)insert(lc(p),l,mid,pos);
    	else insert(rc(p),mid+1,r,pos);
    }
    int query(int p,int l,int r,int ql,int qr)
    {
    	if(!p)return 0;
    	if(l>=ql&&r<=qr)return sum(p);
    	int mid=(l+r)>>1,res=0;
    	if(ql<=mid)res+=query(lc(p),l,mid,ql,qr);
    	if(qr>mid)res+=query(rc(p),mid+1,r,ql,qr);
    	//cerr<<"res::"<<res<<endl;
    	return res;
    }
    int merge(int p,int q,int l,int r)
    {
    	if(!p||!q)return p+q;
    	int x=++tot,mid=(l+r)>>1;
    	sum(x)=sum(p)+sum(q);
    	if(l==r)return x;
    	lc(x)=merge(lc(p),lc(q),l,mid);
    	rc(x)=merge(rc(p),rc(q),mid+1,r);
    	return x;
    }
    struct SAM
    {
    	int tot,last;
    	int fa[maxn],len[maxn];
    	int ch[maxn][30];
    	SAM(){last=tot=1;}
    	inline void add(int c)
    	{
    		int now=++tot;len[now]=len[last]+1;
    		int p=last;last=now;
    		while(p&&!ch[p][c])ch[p][c]=now,p=fa[p];
    		if(!p){fa[now]=1;return;}
    		int q=ch[p][c];
    		if(len[q]==len[p]+1)fa[now]=q;
    		else 
    		{
    			int nowq=++tot;
    			len[nowq]=len[p]+1;
    			memcpy(ch[nowq],ch[q],sizeof(ch[q]));
    			fa[nowq]=fa[q];fa[q]=fa[now]=nowq;
    			while(p&&ch[p][c]==q)ch[p][c]=nowq,p=fa[p];
    		}
    	}
    }sam;
    void dfs(int x)
    {
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		dfs(y);root[x]=merge(root[x],root[y],1,n);
    	}
    }
    inline void solve(int l,int r,char* s)
    {
    	int now=1,tot=1,len=strlen(s+1);
    	while(2333)
    	{
    		ans[tot]='#';
    		for(int i=max(s[tot]-'a'+1,0);i<26;i++)
    			if(sam.ch[now][i]&&query(root[sam.ch[now][i]],1,n,l+tot-1,r)>0)
    			{
    				ans[tot]=i+'a';
    				break;	
    			}
    		if(tot==len+1||!sam.ch[now][s[tot]-'a']||!query(root[sam.ch[now][s[tot]-'a']],1,n,l+tot-1,r))break;
    		now=sam.ch[now][s[tot]-'a'];
    		tot++;
    	}
    	while(tot&&ans[tot]=='#')tot--;
    	if(!tot)puts("-1");
    	else 
    	{
    		for(int i=1;i<tot;i++)putchar(s[i]);
    		putchar(ans[tot]);puts("");
    	}
    }
    int main()
    {
    	scanf("%s",s+1);n=strlen(s+1);
    	for(int i=1;i<=n;i++)sam.add(s[i]-'a'),insert(root[sam.last],1,n,i);
    	for(int i=2;i<=sam.tot;i++)add(sam.fa[i],i);
    	dfs(1);
    	T=read();
    	while(T--)
    	{
    		int l=read(),r=read();
    		scanf("%s",t+1);
    		solve(l,r,t);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Leetcode192. 统计词频
    Leetcode1046. 最后一块石头的重量
    Ubuntu20.04 NS3安装配置
    Ubuntu20.04 中文输入法+截图设置+NetAnim安装
    如何注册谷歌邮箱Gmail
    HDU 2612 Find a way
    友链
    2020沈阳区域赛补题&总结
    XShell中设置便捷的复制粘贴
    Hyper Text 超文本
  • 原文地址:https://www.cnblogs.com/nofind/p/12056458.html
Copyright © 2011-2022 走看看