标签:sign lct math == 修改 splay scanf split root
\(SAM\) + \(LCT\) 维护 \(parent树\)
每次插入一个点对应修改 \(LCT\) 并链加,相当于在链上的 \(\rm endpos\) 中添加一个新的位置。
匹配就在 \(SAM\) 上跑即可。
#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=1200010;
namespace LCT {
int fa[N],ch[N][2],sum[N],add[N],stk[N];
bool tg[N];
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])
#define rev(x) (swap(ls(x),rs(x)),tg[x]^=1)
inline bool isroot(int x) {return ls(fa[x])!=x&&rs(fa[x])!=x;}
inline void spread(int x) {
if(tg[x]) {
if(ls(x)) rev(ls(x));
if(rs(x)) rev(rs(x));
tg[x]=0;
}
if(add[x]) {
if(ls(x)) sum[ls(x)]+=add[x],add[ls(x)]+=add[x];
if(rs(x)) sum[rs(x)]+=add[x],add[rs(x)]+=add[x];
add[x]=0;
}
}
inline void rot(int x) {
R y=fa[x]; R d=ch[y][1]==x;
if(!isroot(y)) ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[x]=fa[y],fa[ch[y][d]=ch[x][d^1]]=y;
fa[ch[x][d^1]=y]=x;
}
inline void Splay(int x) {
R y=x,top=0; stk[++top]=y;
while(!isroot(y)) stk[++top]=y=fa[y];
while(top) spread(stk[top--]);
while(!isroot(x)) {
y=fa[x];
if(!isroot(y)) rot((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
rot(x);
}
}
inline void acc(int x) {for(R y=0;x;x=fa[y=x]) Splay(x),rs(x)=y;}
inline void mrt(int x) {acc(x),Splay(x),rev(x);}
inline int frt(int x) {
acc(x),Splay(x);
while(ls(x)) spread(x),x=ls(x);
Splay(x); return x;
}
inline void split(int x,int y) {mrt(x),acc(y),Splay(x);}
inline void link(int x,int y) {Splay(y),fa[x]=y;}
inline void cut(int x,int y) {split(x,y),fa[y]=rs(x)=0;}
} using namespace LCT;
struct SAM {
int lst,tot;
int fa[N],c[N][26],len[N];
SAM() {lst=tot=1;}
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) {
fa[np]=1,link(np,fa[np]);
split(1,np),++sum[1],++LCT::add[1];
return ;
}
R q=c[p][ch];
if(len[q]==len[p]+1) {
fa[np]=q,link(np,fa[np]);
split(1,np),++sum[1],++LCT::add[1];
return ;
}
R nq=++tot;
memcpy(c[nq],c[q],26<<2);
cut(q,fa[q]);
fa[nq]=fa[q],len[nq]=len[p]+1;
fa[np]=fa[q]=nq;
link(nq,fa[nq]),link(np,fa[np]),link(q,fa[q]);
Splay(q),sum[nq]=sum[q];
while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p];
split(1,np),++sum[1],++LCT::add[1];
}
}s1;
int mask;
string chars;
char S[3000010],s[N];
inline void dec(int mask) {
scanf("%s",S);
chars=S;
for(R j=0,lim=chars.size();j<lim;j++) {
mask=(mask*131+j)%lim;
register char tem=chars[j];
chars[j]=chars[mask];
chars[mask]=tem;
}
}
int n,m;
inline void main() {
m=g(),scanf("%s",s+1);
n=strlen(s+1);
for(R i=1;i<=n;++i)
s1.add(s[i]-'A');
register char op[6];
while(m--) {
scanf("%s",op);
if(op[0]=='A') {
dec(mask);
for(R i=0,lim=chars.size();i<lim;++i)
s1.add(chars[i]-'A');
} else {
dec(mask);
R p=1;
for(R i=0,lim=chars.size();i<lim;++i) {
p=s1.c[p][chars[i]-'A'];
if(!p) break;
} if(!p) puts("0");
else Splay(p),
printf("%d\n",sum[p]),mask^=sum[p];
}
}
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.10
标签:sign lct math == 修改 splay scanf split root
原文地址:https://www.cnblogs.com/Jackpei/p/12177570.html