BZOJ 2555 SubString

题解:用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;
}

  

自己还是太辣鸡了
posted @ 2018-02-19 20:08  ws_zzy  阅读(125)  评论(0编辑  收藏  举报