[CF1037H]Security

Posted by Dispwnl on January 9, 2019

题目

题目大意

给定一个字符串$S$,每次询问给定$l,r$和一个字符串$T$,查询$S[l…r]$中字典序大于$T$的最小的子串,如果没有输出$-1$

Examples

input

baa
5
1 2 ba
2 3 a
1 2 b
2 3 aa
1 3 b

output

-1
aa
ba
-1
ba

input

bacb
4
1 2 ba
2 3 ac
1 3 ac
3 4 c

output

-1
c
b
cb

input

bba
1
1 1 b

output

-1

题解

建好$S$串的$SAM$直接用$T$串在上面递归跑就行,枚举$26$个字符判断一下哪个符合条件,回溯的时候记录答案,至于查询$[l,r]$,用线段树合并一下维护即可

代码

# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
# define tl s[k].l
# define tr s[k].r
# define mid (l+r>>1)
using namespace std;
const int MAX=2e5+5;
struct p{
	int l,r;
}s[MAX<<5];
int n,tot,Q,__L;
int rt[MAX];
char a[MAX],b[MAX];
bool Fl;
void change(int l,int r,int &k,int x)
{
	if(!k) k=++tot;
	if(l==r) return;
	if(x<=mid) change(l,mid,tl,x);
	else change(mid+1,r,tr,x);
}
int merge(int x,int y)
{
	if(!x||!y) return x+y;
	int k=++tot;
	return tl=merge(s[x].l,s[y].l),tr=merge(s[x].r,s[y].r),k;
}
bool ask(int l,int r,int k,int L,int R)
{
	if(r<L||R<l||!k) return 0;
	if(l>=L&&r<=R) return 1;
	return (ask(l,mid,tl,L,R)|ask(mid+1,r,tr,L,R));
}
struct SAM{
	int l,r,L;
	int len[MAX],fa[MAX],tax[MAX],id[MAX];
	int son[MAX][26];
	SAM() {l=r=1;}
	void ins(int x,int id)
	{
		int tt=r;
		len[r=++l]=++L,change(1,n,rt[r],id);
		for(;tt&&!son[tt][x];tt=fa[tt])
		  son[tt][x]=r;
		if(!tt) return void(fa[r]=1);
		int qwq=son[tt][x];
		if(len[qwq]==len[tt]+1) return void(fa[r]=qwq);
		len[++l]=len[tt]+1,fa[l]=fa[qwq],fa[qwq]=fa[r]=l;
		for(int i=0;i<26;++i)
		  son[l][i]=son[qwq][i];
		for(int i=tt;son[i][x]==qwq;i=fa[i])
		  son[i][x]=l;
	}
	void Init()
	{
		for(int i=1;i<=l;++i)
		  ++tax[len[i]];
		for(int i=1;i<=n;++i)
		  tax[i]+=tax[i-1];
		for(int i=l;i>=1;--i)
		  id[tax[len[i]]--]=i;
		for(int i=l;i>=1;--i)
		  if(fa[id[i]]) rt[fa[id[i]]]=merge(rt[fa[id[i]]],rt[id[i]]);
	}
	bool GET_ANS(int l,int r,int _n,int x=1,int RT=1,bool fl=0)
	{
		if(fl) return 1;
		int tt=x>_n?0:a[x]-'a';
		for(int i=tt;i<26;++i)
		  if(son[RT][i]&&ask(1,n,rt[son[RT][i]],l+x-1,r))
		  {
		  	if(i==a[x]-'a')
		  	{
		  		if(GET_ANS(l,r,_n,x+1,son[RT][i],fl)) return b[++__L]=i+'a',1;
			}
			else if(GET_ANS(l,r,_n,x+1,son[RT][i],1)) return b[++__L]=i+'a',1;
		  }
		return fl;
	}
	void Solve(int l,int r,int _n)
	{
		__L=Fl=0;
		if(GET_ANS(l,r,_n))
		{
			for(int i=__L;i>=1;--i)
			  printf("%c",b[i]);
			printf("\n");
		}
		else printf("-1\n");
	}
}_S;
int main()
{
	scanf("%s%d",a+1,&Q),n=strlen(a+1);
	for(int i=1;i<=n;++i)
	  _S.ins(a[i]-'a',i);
	_S.Init();
	for(int i=1,l,r,_n;i<=Q;++i)
	  scanf("%d%d%s",&l,&r,a+1),_n=strlen(a+1),_S.Solve(l,r,_n);
	return 0;
}