CF1037H Security 线段树合并 SAM
LINK:Security
求一个严格大于T的字符串 是原字符串S[L,R]的子串。
容易想到尽可能和T相同 然后再补一个尽可能小的字符即可。
出于这种思想 可以在SAM上先跑匹配 然后枚举加哪个字符 判定即可。
判定s是否在[L,R]中出现过 最快的方法 就是right集了。
这个可以线段树合并完成 注意 合并的时候 需要新建节点 防止把儿子的信息给改了。
倒着贪心即可。空间复杂度大概是nlog^2左右的注意开够。(我也不太会计算空间
const int MAXN=100010;
int n,m,id,len;
int last=1,cnt=1,top;
char a[MAXN<<1],b[MAXN<<1];
struct wy
{
int fa,len;
int ch[26];
}t[MAXN<<1];
int root[MAXN<<1],q[MAXN<<1],c[MAXN<<1],pre[MAXN<<1];
struct jl{int l,r,sum;}s[MAXN*200];
inline void insert(int x)
{
int p=last;
int np=last=++cnt;
len(np)=len(p)+1;
while(p&&!t[p].ch[x])
{
t[p].ch[x]=np;
p=f(p);
}
if(!p)f(np)=1;
else
{
int q=t[p].ch[x];
if(len(p)+1==len(q))f(np)=q;
else
{
int nq=++cnt;
t[nq]=t[q];
len(nq)=len(p)+1;
f(np)=f(q)=nq;
while(p&&t[p].ch[x]==q)
{
t[p].ch[x]=nq;
p=f(p);
}
}
}
}
inline void change(int &p,int l,int r,int x)
{
if(!p)p=++id;
if(l==r){++sum(p);return;}
int mid=(l+r)>>1;
if(x<=mid)change(l(p),l,mid,x);
else change(r(p),mid+1,r,x);
sum(p)=sum(l(p))+sum(r(p));
}
inline void topsort()
{
rep(1,cnt,i)++c[len(i)];
rep(1,cnt,i)c[i]+=c[i-1];
rep(1,cnt,i)q[c[len(i)]--]=i;
}
inline int merge(int x,int y,int l,int r)
{
if(!x||!y)return x|y;
int w=++id;
if(l==r){sum(w)=sum(x)+sum(y);return w;}
int mid=(l+r)>>1;
l(w)=merge(l(x),l(y),l,mid);
r(w)=merge(r(x),r(y),mid+1,r);
sum(w)=sum(l(w))+sum(r(w));
return w;
}
inline int ask(int p,int l,int r,int L,int R)
{
if(!p||L>R)return 0;
if(L<=l&&R>=r)return sum(p);
int mid=(l+r)>>1,ww=0;
if(L<=mid)ww+=ask(l(p),l,mid,L,R);
if(R>mid)ww+=ask(r(p),mid+1,r,L,R);
return ww;
}
int main()
{
freopen("1.in","r",stdin);
gc(a);len=strlen(a+1);
rep(1,len,i)insert(a[i]-'a'),change(root[last],1,len,i);
topsort();gt(n);
fep(cnt,2,i)root[f(q[i])]=merge(root[f(q[i])],root[q[i]],1,len);
rep(1,n,i)
{
int x,y;
gt(x);gt(y);gc(b);
int now=1,last=-1,flag=0;top=0;
int len1=strlen(b+1);
rep(1,len1,j)
{
int cc=b[j]-'a';
if(t[now].ch[cc])pre[t[now].ch[cc]]=now,now=t[now].ch[cc],a[++top]=b[j];
else {last=b[j]-'a';break;}
}
while(now)
{
rep(last+1,25,j)
{
if(flag)break;
int ww=t[now].ch[j];
if(ww)
{
if(ask(root[ww],1,len,x+top,y))
{
a[++top]=j+'a';
flag=1;
}
}
}
if(flag)break;
now=pre[now];last=b[top]-'a';
--top;
}
if(!flag){puts("-1");}
else {rep(1,top,i)printf("%c",a[i]);puts("");}
}
return 0;
}