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;
}
posted @ 2019-12-17 19:50  nofind  阅读(140)  评论(0编辑  收藏  举报