解析
算是一个比较高级的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_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
cin>>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;
}
/*
*/