题目描述:
题目分析:
要求 S 1 S_1 S1字典序尽量小,又要严格大于 T T T。那么最优肯定是尽可能前面一段与 T T T相同,然后下一个字符大于 T T T。
又因为 S 1 S_1 S1是 S S S的子串,所以可以建出 S S S的后缀自动机,然后找到 T T T的前缀能够匹配的最长长度 l e n len len,那么对于 i ∈ [ 1 , l e n + 1 ] i\in[1,len+1] i∈[1,len+1],我们想要找到最大的一个 i i i,使得 S 1 [ 1 , i − 1 ] = T [ 1 , i − 1 ] S_1[1,i-1]=T[1,i-1] S1[1,i−1]=T[1,i−1], S [ i ] > T [ i ] S[i]>T[i] S[i]>T[i]。
直接从大到小枚举 i i i,然后枚举后缀自动机上一条 > T [ i ] >T[i] >T[i]的转移链,如果其对应的串在 [ l , r ] [l,r] [l,r]中出现了,那么就找到了答案。
判断后缀自动机上一个节点代表的长度为 k k k 的串是否在一个区间出现,只需要它的 e n d p o s endpos endpos集合包含 [ l + k − 1 , r ] [l+k-1,r] [l+k−1,r] 中的点,在 f a i l fail fail树上线段树可持久化线段树合并即可。
Code:
#include<bits/stdc++.h>
#define maxn 200005
#define maxp maxn*18
using namespace std;
int n,m,rt[maxn],lc[maxp],rc[maxp],sz;
char s[maxn];
void ins(int &i,int l,int r,int x){
i=++sz;
if(l==r) return;
int mid=(l+r)>>1;
x<=mid?ins(lc[i],l,mid,x):ins(rc[i],mid+1,r,x);
}
int merge(int x,int y,int l,int r){
if(!x||!y||l==r) return x+y;
int i=++sz,mid=(l+r)>>1;
lc[i]=merge(lc[x],lc[y],l,mid),rc[i]=merge(rc[x],rc[y],mid+1,r);
return i;
}
bool qry(int i,int l,int r,int x,int y){
if(!i) return 0;
if(x<=l&&r<=y) return 1;
int mid=(l+r)>>1;
if(x<=mid&&qry(lc[i],l,mid,x,y)) return 1;
if(y>mid&&qry(rc[i],mid+1,r,x,y)) return 1;
return 0;
}
namespace SAM{
int fa[maxn]={-1},ch[maxn][26],len[maxn],last,sz;
void extend(int c,int pos){
int cur=++sz,p=last,q; len[last=cur]=len[p]+1,ins(rt[cur],1,n,pos);
for(;~p&&!ch[p][c];p=fa[p]) ch[p][c]=cur;
if(p==-1) fa[cur]=0;
else if(len[q=ch[p][c]]==len[p]+1) fa[cur]=q;
else{
int clone=++sz; len[clone]=len[p]+1,memcpy(ch[clone],ch[q],sizeof ch[q]);
fa[clone]=fa[q],fa[cur]=fa[q]=clone;
for(;~p&&ch[p][c]==q;p=fa[p]) ch[p][c]=clone;
}
}
}
using SAM::ch;
vector<int>G[maxn];
void dfs(int u){for(int i=G[u].size()-1,v;i>=0;i--) dfs(v=G[u][i]),rt[u]=merge(rt[u],rt[v],1,n);}
int main()
{
scanf("%s%d",s+1,&m),n=strlen(s+1);
for(int i=1;i<=n;i++) SAM::extend(s[i]-'a',i);
for(int i=1;i<=SAM::sz;i++) G[SAM::fa[i]].push_back(i);
dfs(0),rt[0]=0;
static int stk[maxn],tp;
for(int l,r,len;m--;){
scanf("%d%d%s",&l,&r,s+1),len=strlen(s+1),stk[tp=1]=0,s[len+1]='a'-1;
for(int i=1,p=0;i<=len&&ch[p][s[i]-'a'];i++) stk[++tp]=p=ch[p][s[i]-'a'];
bool flg=0;
for(int i=min(r-l+1,tp);i>=1&&!flg;i--)
for(int j=s[i]+1-'a';j<26;j++)
if(qry(rt[ch[stk[i]][j]],1,n,l+i-1,r)){
for(int k=1;k<i;k++) putchar(s[k]);
putchar(j+'a'),putchar('\n'),flg=1; break;
}
if(!flg) puts("-1");
}
}