说实话做这个题之前我都不知道CF有H题
字典序尽量小又要严格大于模式串,记模式串为$S$,则贪心让前面最多的字符和$S$相同,在后面再补一个比$S$大且最小的字符。
则最优的方案一定是在$S$后面补一个尽可能小的字符。如果补不了,就倒着枚举位置,如果当前位置$i$能替换为一个比$S_i$大的字符,找到最小的可替换字符$c$换掉它。答案就是$S(1\sim i-1)+’c’$。
以下用“好点”表示包含$[L,R]$子串的节点。
先把母串的$SAM$造出来。
对每个模式串,找出仅走“好点”,能匹配的最大长度$max\underline{}len$。同时找出每个位置$i$最小的字符$nex$,满足$c>S_i$且从$i-1$匹配的节点走$nex$边的儿子为“好点”(没有为$-1$)。
从$max\underline{}len$倒着枚举,找到第一个不为$-1$的位置$i$,$S(1\sim i-1)+nex_i$即为答案。
至于怎么判断一个节点是否为“好点”,用线段树合并获取每个节点$endpos$的所有元素。假设当前走到的长度为$i$,$endpos$中存在$pos$满足$pos\in [L,R]$且$pos-i+1\in [L,R]$的节点为“好点”。合起来就是$pos\in [L+i-1,R]$。
空间$O(n\log n)$,时间$O(26n\log n)$(实际情况远跑不满)
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 400005
#define inf 0x3f3f3f3f
using namespace std;
inline int read(){
int x=0,y=0;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return y?-x:x;
}
#define son(x,y) son[x][y]
#define ls(x) ls[x]
#define rs(x) rs[x]
int h[maxn],root[maxn],ls[maxn<<5],rs[maxn<<5],all,num;
int son[maxn][26],len[maxn],fa[maxn],nex[maxn],last=1,cnt=1,n,N;
char s[maxn];
struct edge{
int pre,to;
}e[maxn];
inline void add(int from,int to){
e[++num].pre=h[from],h[from]=num,e[num].to=to;
}
void modify(int poi,int l,int r,int &node){
node=++all;
if(l==r)return;
int mid=l+r>>1;
if(poi<=mid)modify(poi,l,mid,ls(node));
else modify(poi,mid+1,r,rs(node));
}
int merge(int x,int y,int l,int r){
if(!x||!y||l==r)return x|y;
int ne=++all,mid=l+r>>1;
ls(ne)=merge(ls(x),ls(y),l,mid);
rs(ne)=merge(rs(x),rs(y),mid+1,r);
return ne;
}
bool ask(int L,int R,int l,int r,int node){
if(!node)return 0;
if(L<=l&&R>=r)return 1;
int mid=l+r>>1;
if(L<=mid&&ask(L,R,l,mid,ls(node)))return 1;
if(R>mid&&ask(L,R,mid+1,r,rs(node)))return 1;
return 0;
}//询问endpos在[L,R]中是否有元素
void insert(int c){
int p=last,ne=last=++cnt;
modify(len[ne]=len[p]+1,1,N,root[ne]);
while(p&&!son(p,c))son(p,c)=ne,p=fa[p];
if(!p)fa[ne]=1;
else {
int q=son(p,c);
if(len[q]==len[p]+1)fa[ne]=q;
else {
int sp=++cnt;
memcpy(son[sp],son[q],sizeof son[q]);
fa[sp]=fa[q],len[sp]=len[p]+1,fa[q]=fa[ne]=sp;
while(p&&son(p,c)==q)son(p,c)=sp,p=fa[p];
}
}
}
void dfs(int node=1){
int x;
for(register int i=h[node];i;i=e[i].pre)
x=e[i].to,dfs(x),root[node]=merge(root[node],root[x],1,N);
}//求endpos集合
int main(){
scanf("%s",s+1),N=strlen(s+1);
for(register int i=1;i<=N;++i)insert(s[i]-'a');
for(register int i=2;i<=cnt;++i)add(fa[i],i);
dfs();
int m=read(),l,r,node,x,i;
while(m--){
l=read(),r=read(),node=1;
scanf("%s",s+1),n=strlen(s+1);
for(i=1;;++i){
nex[i]=-1;
for(register int j=max(s[i]-'a'+1,0);j<26;++j){
x=son(node,j);
if(x&&ask(l+i-1,r,1,N,root[x])){
nex[i]=j;
break;
}
}
x=son(node,s[i]-'a');
if(!x||i==n+1||!ask(l+i-1,r,1,N,root[x]))break;
node=x;
}
while(i&&nex[i]==-1)--i;
if(!i)puts("-1");//找不到,无解
else {
for(register int j=1;j<i;++j)px(s[j]);
px(nex[i]+'a');
pn;
}
}
}