解析
算是一个比较高级的SAM的应用了
对fail树的dfs序建立维护右端点最大值的线段树
考虑把所有的询问离线,按照右端点排序
每次动态把当前询问右端点左侧的前缀插入线段树
处理询问时,先贪心的尝试和询问串填法一样,如果不行就往下一个字母填
判断合法的标志就是左端点的最大值是否不小于询问的左端点
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=2e5+100;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
int n,m;
struct node{int len,fa;int tr[26];
}st[N];
int tot(1),lst(1),id[N];
void ins(int c,int ide){c-='a';int cur=++tot,p=lst;lst=tot;st[cur].len=st[p].len+1;id[ide]=cur;for(;p&&!st[p].tr[c];p=st[p].fa) st[p].tr[c]=cur;if(!st[p].tr[c]) st[cur].fa=1;else{int q=st[p].tr[c];if(st[q].len==st[p].len+1) st[cur].fa=q;else{int pp=++tot;st[pp]=st[q];st[pp].len=st[p].len+1;st[q].fa=st[cur].fa=pp;for(;p&&st[p].tr[c]==q;p=st[p].fa) st[p].tr[c]=pp;return;}}
}struct
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
segment_tree{int mx[N<<2];int ask(int k,int l,int r,int x,int y){if(x<=l&&r<=y) return mx[k];int res=0;if(x<=mid) res=max(res,ask(ls,l,mid,x,y));if(y>mid) res=max(res,ask(rs,mid+1,r,x,y)); //if(k==1) printf("---ask: (%d %d) res=%d\n",x,y,res);return res;}void upd(int k,int l,int r,int p,int w){//if(k==1) printf("---upd: p=%d w=%d\n",p,w);if(l==r){mx[k]=max(mx[k],w);return;}if(p<=mid) upd(ls,l,mid,p,w);else upd(rs,mid+1,r,p,w);mx[k]=max(mx[ls],mx[rs]);return;}
}t;string s,ss,ask[N],ans[N];
struct query{int id,l,r,len;bool operator < (const query o)const{return r<o.r;}
}q[N];
int St[N],tim,Ed[N];
vector<int>v[N];
void dfs(int x){St[x]=++tim;for(const auto &to:v[x]) dfs(to);Ed[x]=tim;return;
}
bool jd[N];
inline bool check(int x,int l,int len){//printf(" check:x=%d l=%d len=%d ask=%d\n",x,l,len,t.ask(1,1,tim,St[x],Ed[x]));return t.ask(1,1,tim,St[x],Ed[x])-len+1>=l;
}
bool find(int x,int len,int o,int idx){if(len>q[idx].len){for(int i=0;i<=25;i++){if(st[x].tr[i]&&check(st[x].tr[i],q[idx].l,len)){jd[o]=1;ans[o]+='a'+i;//printf("ok x=%d to=%d\n",x,st[x].tr[i]);return true;}}return false;} int c=ask[o][len]-'a';//printf("x=%d len=%d c=%d\n",x,len,c);if(st[x].tr[c]&&check(st[x].tr[c],q[idx].l,len)&&find(st[x].tr[c],len+1,o,idx)){ans[o]+='a'+c;return true;}else{for(int i=c+1;i<=25;i++){ if(st[x].tr[i]&&check(st[x].tr[i],q[idx].l,len)){//printf("?? o=%d ask=%d len=%d\n",o,t.ask(1,1,tim,St[st[x].tr[i]],Ed[st[x].tr[i]]),len);jd[o]=1;ans[o]+='a'+i;return true;}}return false;}
}
signed main(){
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifcin>>s;s.insert(s.begin(),' ');n=s.size()-1;for(int i=1;i<=n;i++) ins(s[i],i);for(int i=2;i<=tot;i++) v[st[i].fa].push_back(i);dfs(1);//for(int i=1;i<=tot;i++) printf("i=%d fa=%d (%d %d)\n",i,st[i].fa,St[i],Ed[i]);m=read();for(int i=1;i<=m;i++){q[i].l=read();q[i].r=read();q[i].id=i;cin>>ask[i];ask[i].insert(ask[i].begin(),' ');//if(i==75){//printf("(%d %d) ",q[i].l,q[i].r);cout<<ask[i]<<endl;//}q[i].len=ask[i].size()-1;}sort(q+1,q+1+m);int pl=0;for(int i=1;i<=m;i++){while(pl<q[i].r){++pl;t.upd(1,1,tim,St[id[pl]],pl);//printf("upd: node=%d pos=%d\n",id[pl],St[id[pl]]);}find(1,1,q[i].id,i);}for(int i=1;i<=m;i++){if(!jd[i]) printf("-1\n");else{for(int j=ans[i].size()-1;j>=0;j--) putchar(ans[i][j]);putchar('\n');}}return 0;
}
/*
*/