The meaning of problems
https://codeforces.com/contest/1037/problem/H
Think
Greedy idea is to read as much as possible to find the string section of the prefix, and then one more for lexicographical relatively large characters.
First establish the original string SAM, taking into account the range limitations, the need to merge tree line maintenance endpos collection.
For an inquiry, we now find its prefix corresponding node on SAM. If there is, continue; otherwise, no need to look anymore. This process back then, whenever a node appears greater than the current character of the side, directly output the answer.
Time complexity $ O (26 * n * logn) $.
Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1E5+5; 4 int n; 5 int size,head[maxn*4]; 6 int cnt,root[maxn*40],ls[maxn*40],rs[maxn*40],ans[maxn*40],what[maxn*40]; 7 struct edge 8 { 9 int to,next; 10 }E[maxn*2]; 11 inline void addE(int u,int v) 12 { 13 E[++size].to=v; 14 E[size].next=head[u]; 15 head[u]=size; 16 } 17 struct tree 18 { 19 int fa,len,ch[26]; 20 }; 21 void out(int l,int r,int num) 22 { 23 if(l==r) 24 { 25 cout<<l<<" "; 26 return; 27 } 28 int mid=(l+r)>>1; 29 if(ls[num]) 30 out(l,mid,ls[num]); 31 if(rs[num]) 32 out(mid+1,r,rs[num]); 33 } 34 void insertT(int l,int r,int pos,int&num,int pre) 35 { 36 num=++cnt; 37 ls[num]=ls[pre],rs[num]=rs[pre]; 38 if(l==r) 39 { 40 ans[num]=pos; 41 return; 42 } 43 int mid=(l+r)>>1; 44 if(pos<=mid) 45 insertT(l,mid,pos,ls[num],ls[pre]); 46 else 47 insertT(mid+1,r,pos,rs[num],rs[pre]); 48 ans[num]=max(ans[ls[num]],ans[rs[num]]); 49 } 50 int merge(int l,int r,int a,int b) 51 { 52 if(!a||!b) 53 return a|b; 54 int num=++cnt; 55 ans[num]=max(ans[a],ans[b]); 56 if(l==r) 57 return num; 58 int mid=(l+r)>>1; 59 ls[num]=merge(l,mid,ls[a],ls[b]); 60 rs[num]=merge(mid+1,r,rs[a],rs[b]); 61 ans[num]=max(ans[ls[num]],ans[rs[num]]); 62 return num; 63 } 64 int ask(int L,int R,int l,int r,int num) 65 { 66 if(!num) 67 return 0; 68 if(L<=l&&r<=R) 69 return ans[num]; 70 int mid=(l+r)>>1; 71 if(R<=mid) 72 return ask(L,R,l,mid,ls[num]); 73 else if(mid<L) 74 return ask(L,R,mid+1,r,rs[num]); 75 return max(ask(L,R,l,mid,ls[num]),ask(L,R,mid+1,r,rs[num])); 76 } 77 void dfs(int u) 78 { 79 for(int i=head[u];i;i=E[i].next) 80 { 81 int v=E[i].to; 82 dfs(v); 83 root[u]=merge(1,n,root[u],root[v]); 84 } 85 if(what[u]) 86 insertT(1,n,what[u],root[u],root[u]); 87 } 88 struct SAM 89 { 90 tree t[maxn*2]; 91 int last,tot; 92 SAM() 93 { 94 last=tot=1; 95 } 96 inline void add(int x,int pos) 97 { 98 int u=last,now=++tot; 99 last=tot; 100 what[now]=pos; 101 t[now].len=t[u].len+1; 102 for(;u&&!t[u].ch[x];u=t[u].fa) 103 t[u].ch[x]=now; 104 if(!u) 105 t[now].fa=1; 106 else 107 { 108 int v=t[u].ch[x]; 109 if(t[v].len==t[u].len+1) 110 t[now].fa=v; 111 else 112 { 113 int w=++tot; 114 t[w]=t[v]; 115 t[w].len=t[u].len+1; 116 t[now].fa=t[v].fa=w; 117 for(;u&&t[u].ch[x]==v;u=t[u].fa) 118 t[u].ch[x]=w; 119 } 120 } 121 } 122 void build() 123 { 124 for(int i=2;i<=tot;++i) 125 addE(t[i].fa,i); 126 } 127 }T; 128 int wait[maxn*2]; 129 void solve() 130 { 131 int L,R; 132 string str; 133 cin>>L>>R>>str; 134 int pos=1,top=0; 135 wait[top++]=pos; 136 for(int i=0;i<str.size();++i) 137 { 138 int x=str[i]-'a'; 139 if(T.t[pos].ch[x]) 140 { 141 pos=T.t[pos].ch[x]; 142 x=ask(L,R,1,n,root[pos]); 143 if(x-i<L) 144 break; 145 wait[top++]=pos; 146 } 147 else 148 break; 149 } 150 for(int i=top-1;i>=0;--i) 151 { 152 int x=max(str[i]-'a',-1); 153 for(int j=x+1;j<26;++j) 154 if(T.t[wait[i]].ch[j]) 155 { 156 int pos=T.t[wait[i]].ch[j]; 157 int x=ask(L,R,1,n,root[pos]); 158 if(x-i>=L) 159 { 160 for(int k=0;k<i;++k) 161 cout<<str[k]; 162 cout<<char('a'+j)<<endl; 163 return; 164 } 165 } 166 } 167 cout<<-1<<endl; 168 } 169 int main() 170 { 171 ios::sync_with_stdio(false); 172 string str; 173 cin>>str; 174 n=str.size(); 175 for(int i=0;i<str.size();++i) 176 T.add(str[i]-'a',i+1); 177 T.build(); 178 dfs(1); 179 int T; 180 cin>>T; 181 while(T--) 182 solve(); 183 return 0; 184 }