21.7.2 t2
tag:SAM,LCT,线段树
LCT+SAM维护endpos套路,先建出SAM,然后从左到右Access(pos[i])的同时处理询问。
每次Access的时候到根链会分成若干段,每段的endpos相同,所以对于这个点代表的某个串来说,当询问的 \(l\le endpos-len+1\) 时,这个串就可以对询问区间产生贡献。
具体来说,假设当前点代表的最长串为 \([x,endpos]\),那么
- \(l\in[x,endpos]\),贡献为 \(endpos-l+1\)
- \(l<x\),贡献为 \(endpos-x+1\)
所以用线段树维护每个点的 \(mxendpos\) 和 \(mxans\) 即可。
由于要将到根链的endpos都改为i,所以LCT的splay要支持区间覆盖。
#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void Read(T &n){
char ch; bool flag=false;
while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
if(flag)n=-n;
}
enum{
MAXN = 100005
};
int n, Q, curpos;
char a[MAXN];
namespace SGT{
struct node{
int ans, mxr;
node(int ans=0, int mxr=0):ans(ans),mxr(mxr){}
#define ans(x) t[x].ans
#define mxr(x) t[x].mxr
}t[MAXN<<2];
inline int lc(int x){return x<<1;}
inline int rc(int x){return x<<1|1;}
void Update(int x, int head, int tail, int l, int r, int ans, int mxr){
if(l<=head and tail<=r) return ans(x) = max(ans(x),ans), mxr(x) = max(mxr(x),mxr), void();
int mid = head+tail >> 1;
if(l<=mid) Update(lc(x),head,mid,l,r,ans,mxr);
if(mid<r) Update(rc(x),mid+1,tail,l,r,ans,mxr);
}
inline pair<int,int> Query(int pos){
int x=1, head=1, tail=n, ans=ans(1), mxr=mxr(1);
while(head<tail){
int mid = head+tail >> 1;
if(pos<=mid) x = lc(x), tail = mid;
else x = rc(x), head = mid+1;
ans = max(ans,ans(x));
mxr = max(mxr,mxr(x));
}
return make_pair(ans,mxr);
}
}
using SGT::Update;
using SGT::Query;
namespace LCT{
struct node{
int fa, son[2], val, mx, ed, fil;
#define fa(x) t[x].fa
#define lc(x) t[x].son[0]
#define rc(x) t[x].son[1]
#define val(x) t[x].val
#define mx(x) t[x].mx
#define ed(x) t[x].ed
#define fil(x) t[x].fil
}t[MAXN<<1];
inline char Is_Root(int x){return lc(fa(x))!=x and rc(fa(x))!=x;}
inline char Which(int x){return rc(fa(x))==x;}
inline void Push_Up(int x){
mx(x) = val(x);
if(lc(x)) mx(x) = max(mx(lc(x)),mx(x));
if(rc(x)) mx(x) = max(mx(rc(x)),mx(x));
}
inline void Fill(int x, int fil){fil(x) = ed(x) = fil;}
inline void Push_Down(int x){
if(fil(x)){
if(lc(x)) Fill(lc(x),fil(x));
if(rc(x)) Fill(rc(x),fil(x));
fil(x) = 0;
}
}
inline void Rotate(int x){
int y=fa(x), z=fa(y), k=Which(x), u=t[x].son[!k];
if(!Is_Root(y)) t[z].son[Which(y)]=x; fa(x)=z;
if(u) fa(u)=y; t[y].son[k]=u;
fa(y)=x; t[x].son[!k]=y;
Push_Up(y); Push_Up(x);
}
inline void Splay(int x){
static int q[MAXN<<1], top;
q[top=1] = x; for(int i=x; !Is_Root(i); i=fa(i)) q[++top] = fa(i);
for(int i=top; i; i--) Push_Down(q[i]);
while(!Is_Root(x)){
int y=fa(x);
if(!Is_Root(y)) Rotate(Which(x)==Which(y)?y:x);
Rotate(x);
}
}
inline void Access(int x){
int tx=x;
for(int y=0; x; y=x, x=fa(x)){
Splay(x);
rc(x) = 0; Push_Up(x);
if(ed(x) and mx(x)){
int l=ed(x)-mx(x)+1, r=ed(x);
if(l>1) Update(1,1,n,1,l-1,r-l+1,0);
Update(1,1,n,l,r,0,r);
}
rc(x) = y; Push_Up(x);
}
Splay(tx); Fill(tx,curpos);
assert(lc(1)==0);
}
}
struct node{
int fa, son[26], len;
#define son(x,opt) t[x].son[opt]
#define len(x) t[x].len
}t[MAXN<<1];
int node_cnt=1, prv=1;
inline int insert(char v){
int x = ++node_cnt; len(x) = len(prv)+1;
while(prv and !son(prv,v)) son(prv,v) = x, prv = fa(prv);
if(!prv) fa(x) = 1;
else{
int p = son(prv,v);
if(len(p) == len(prv)+1) fa(x) = p;
else{
int new_p = ++node_cnt; len(new_p) = len(prv)+1;
fa(new_p) = fa(p); fa(p) = fa(x) = new_p;
copy(t[p].son,t[p].son+26,t[new_p].son);
while(prv and son(prv,v)==p) son(prv,v) = new_p, prv = fa(prv);
}
}
return prv=x;
}
struct quest{
int l, r, id;
inline bool operator <(const quest &k)const{return r<k.r;}
}q[MAXN];
int ans[MAXN], pos[MAXN];
int main(){
// freopen("2.in","r",stdin);
scanf("%s",a+1); n = strlen(a+1); Read(Q);
for(int i=1; i<=Q; i++) Read(q[i].l), Read(q[i].r), q[i].id = i;
sort(q+1,q+Q+1);
for(int i=1; i<=n; i++) pos[i] = insert(a[i]-'a');
for(int i=2; i<=node_cnt; i++) LCT::fa(i) = fa(i), LCT::mx(i) = LCT::val(i) = len(i);
for(int i=1, it=1; i<=n; i++){
curpos = i;
LCT::Access(pos[i]);
while(it<=Q and q[it].r==i){
pair<int,int> tmp = Query(q[it].l);
ans[q[it].id] = max(tmp.first,tmp.second-q[it].l+1);
it++;
}
}
for(int i=1; i<=Q; i++) printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号