题解:用LCT维护parent树的Right集合大小
为什么我的代码这么慢???
问题:对SAM理解的还不够深
吐槽:神加密
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1200009;
int T;
int fa[maxn],ch[maxn][2],tag[maxn],v[maxn],rev[maxn];
inline int son(int x){
if(ch[fa[x]][1]==x)return 1;
else return 0;
}
inline bool isroot(int x){
return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
}
inline void pushup(int x){
}
inline void pushdown(int x){
if(tag[x]){
tag[ch[x][0]]+=tag[x];
tag[ch[x][1]]+=tag[x];
v[ch[x][0]]+=tag[x];
v[ch[x][1]]+=tag[x];
tag[x]=0;
}
if(rev[x]){
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
rev[x]^=1;
swap(ch[x][0],ch[x][1]);
}
}
void Downfa(int x){
if(!isroot(x))Downfa(fa[x]);
pushdown(x);
}
inline void Rotate(int x){
int y=fa[x];
int z=fa[y];
int b=son(x),c=son(y);
int a=ch[x][b^1];
if(!isroot(y))ch[z][c]=x;
fa[x]=z;
if(a)fa[a]=y;
ch[y][b]=a;
fa[y]=x;ch[x][b^1]=y;
pushup(y);pushup(x);
}
void Splay(int x){
Downfa(x);
while(!isroot(x)){
int y=fa[x];
if(isroot(y)){
Rotate(x);
}else{
if(son(x)==son(y)){
Rotate(y);Rotate(x);
}else{
Rotate(x);Rotate(x);
}
}
}
}
void Access(int x){
for(int t=0;x;t=x,x=fa[x]){
Splay(x);ch[x][1]=t;pushup(x);
}
}
void Makeroot(int x){
Access(x);Splay(x);rev[x]^=1;
}
void Linkp(int x,int y){
Makeroot(x);fa[x]=y;
}
void Cutp(int x,int y){
Makeroot(x);Access(y);Splay(y);
fa[ch[y][0]]=0;ch[y][0]=0;pushup(y);
}
void Addpath(int x,int y){
Makeroot(x);Access(y);Splay(y);
tag[y]+=1;v[y]+=1;
}
int SAMsiz,last,cur;
int ch2[maxn][27];
int dis[maxn];
int par[maxn];
void BuildSAM(int c,int idp){
cur=++SAMsiz;
dis[cur]=idp;
int p=last;last=cur;
for(;p&&!ch2[p][c];p=par[p])ch2[p][c]=cur;
if(!p){
par[cur]=1;
Linkp(cur,1);
Addpath(1,cur);
}else{
int q=ch2[p][c];
if(dis[q]==dis[p]+1){
par[cur]=q;
Linkp(cur,q);
Addpath(1,cur);
}else{
int nt=++SAMsiz;
memcpy(ch2[nt],ch2[q],sizeof(ch2[nt]));
dis[nt]=dis[p]+1;
Cutp(q,par[q]);
Linkp(q,nt);
Linkp(nt,par[q]);
Linkp(cur,nt);
Splay(q);Splay(nt);
v[nt]=v[q];
Addpath(1,cur);
par[nt]=par[q];
par[q]=par[cur]=nt;
for(;ch2[p][c]==q;p=par[p])ch2[p][c]=nt;
}
}
}
int mask,m,nowlen;
char opty[maxn];
char opts[maxn];
void Decode(){
// return;
int t=mask;
for(int i=0;i<m;++i){
t=(t*131+i)%m;
swap(opts[i],opts[t]);
}
}
void Addstring(){
for(int i=0;i<m;++i)BuildSAM(opts[i]-‘A‘,nowlen+i+1);
nowlen+=m;
}
int Getans(){
int x=1;
for(int i=0;i<m;++i){
int c=opts[i]-‘A‘;
x=ch2[x][c];
}
if(!x)return 0;
Splay(x);
return v[x];
}
int main(){
scanf("%d",&T);
SAMsiz=last=1;
scanf("%s",opts);
nowlen=m=strlen(opts);
for(int i=0;i<m;++i)BuildSAM(opts[i]-‘A‘,i+1);
while(T--){
scanf("%s%s",opty,opts);
m=strlen(opts);
Decode();
if(opty[0]==‘A‘){
Addstring();
}else{
int ans=Getans();
printf("%d\n",ans);
mask^=ans;
}
}
return 0;
}