题意

显然是贪心。

先建出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;
}
12-25 07:38