CF1037H Security
题意:给出一个字符串 \(S\) ,给出 \(Q\) 个操作,给出\(L\) , \(R\) , \(T\) ,求字典序最小的\(S_1\),使得\(S_1\)为\(S[L..R]\)的子串,且\(S_1\)的字典序严格大于\(T\)。输出这个\(S_1\),如果无解输出\(-1\)。
\(SAM\) + 线段树合并
利用在 \(parent树\) 线段树合并维护 \({\rm endpos}(p)\) 并解决区间 \([l,r]\) 限制。
所以直接贪心地在 \(SAM\) 上跑,使跑出来的串尽可能接近 \(T\) ,即 \(S_1,{\rm strlen}(S_1)=n\) 中的 \([1,n-1]\) 与 \(T\) 的 \([1,n-1]\) 时相同的,只有第 \(n\) 位是不同的。
#include<iostream>
#include<cstdio>
#include<cstring>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=1000010,B=30;
int n,lst=1,tot=1,num;
int len[N],fa[N],c[N][26],d[N],mem[N];
char s[N],ans[N];
inline void add(int ch) {
R p=lst,np=lst=++tot;
len[np]=len[p]+1;
while(p&&!c[p][ch]) c[p][ch]=np,p=fa[p];
if(!p) return fa[np]=1,void();
R q=c[p][ch];
if(len[q]==len[p]+1) fa[np]=q;
else {
R nq=++tot;
memcpy(c[nq],c[q],26<<2);
fa[nq]=fa[q],len[nq]=len[p]+1;
fa[np]=fa[q]=nq;
while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p];
}
}
int rt[N],ls[N*B],rs[N*B],sum[N*B];
inline void change(int& tr,int l,int r,int p) {
if(!tr) tr=++num;
++sum[tr]; if(l==r) return ;
R md=(l+r)>>1;
p<=md?change(ls[tr],l,md,p):change(rs[tr],md+1,r,p);
}
inline bool query(int tr,int l,int r,int LL,int RR) {
if(LL<=l&&r<=RR) return sum[tr]; R md=(l+r)>>1;
return (LL<=md&&ls[tr]&&query(ls[tr],l,md,LL,RR))
||(RR>md&&rs[tr]&&query(rs[tr],md+1,r,LL,RR));
}
inline int merge(int tr,int t,int l,int r) {
if(!tr||!t) return tr+t;
R p=++num,md=(l+r)>>1;
sum[p]=sum[tr]+sum[t];
if(l==r) return p;
ls[p]=merge(ls[tr],ls[t],l,md);
rs[p]=merge(rs[tr],rs[t],md+1,r);
return p;
}
inline void solve(int l,int r) {
R p=1,tot=1,m=strlen(s+1),ch;
while(20040109) {
ch=s[tot]-'a';
ans[tot]='#';
for(R i=max(ch+1,0);i<26;++i)
if(c[p][i]&&query(rt[c[p][i]],1,n,l+tot-1,r)) {
ans[tot]=i+'a'; break;
}
if(tot==m+1||!c[p][ch]||
!query(rt[c[p][ch]],1,n,l+tot-1,r)) break;
p=c[p][ch];
++tot;
} while(tot&&ans[tot]=='#') --tot;
if(!tot) return puts("-1"),void();
for(R i=1;i<tot;++i) putchar(s[i]);
putchar(ans[tot]),putchar(10);
}
inline void main() {
scanf("%s",s+1),n=strlen(s+1);
for(R i=1;i<=n;++i)
add(s[i]-'a'),change(rt[lst],1,n,i);
for(R i=1;i<=tot;++i) ++d[len[i]];
for(R i=1;i<=n;++i) d[i]+=d[i-1];
for(R i=1;i<=tot;++i) mem[d[len[i]]--]=i;
for(R i=tot;i;--i) { R u=mem[i];
rt[fa[u]]=merge(rt[fa[u]],rt[u],1,n);
} R T=g(); while(T--) {
R l=g(),r=g();
scanf("%s",s+1);
solve(l,r);
}
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.10