BZOJ2555: SubString

题面:https://www.lydsy.com/JudgeOnline/problem.php?id=2555
题解:
如果没有修改操作,这就是一道SAM模板题。
有了修改操作后,发现fail树可能会有断边的过程,
不难想到使用LCT维护fail树。
每次加边时,需要将贡献也一并加入LCT的节点中,
查询时,找到对应节点,将其splay到根,此时的val就是答案。
注意:
1.splay时记得要pushdown;
2.是大写字母;
3.数组要开到\(1.2e6\)
时间复杂度:\(O(n+Qlogn)\)
代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
char c[3030000];
int n,m,Q;
namespace LCT{
	int fa[1202000],ch[1202000][2],laz[1202000],w[1202000];
	int st[1202000];
	IN nroot(int x){
		return (ch[fa[x]][0]==x)||(ch[fa[x]][1]==x);
	}
	IN get(int x){
		return ch[fa[x]][1]==x;
	}
	I add(int x,int val){
		if(!x)return;laz[x]+=val;w[x]+=val;
	}
	I push_down(int x){
		add(ch[x][0],laz[x]);add(ch[x][1],laz[x]);
		laz[x]=0;
	}
	I rotate(int x){
		re y=fa[x],z=fa[y],dir=get(x);
		if(nroot(y))ch[z][get(y)]=x;fa[x]=z;
		ch[y][dir]=ch[x][dir^1];fa[ch[x][dir^1]]=y;
		ch[x][dir^1]=y;fa[y]=x;
	}
	I splay(int x){
		re y=x,z=0;st[++z]=y;
		while(y)st[++z]=y=fa[y];
		while(z)push_down(st[z--]);
		while(nroot(x)){
			y=fa[x],z=fa[y];
			if(nroot(y))rotate((get(x)^get(y))?x:y);
			rotate(x);
		}
	}
	I access(int x){
		for(re y=0;x;x=fa[y=x])splay(x),ch[x][1]=y;
	}
	I link(int x,int y){
		fa[x]=y;access(y);splay(y);add(y,w[x]);
	}
	I cut(int x,int y){
		access(x);splay(x);add(ch[x][0],-w[x]);
		fa[ch[x][0]]=0;ch[x][0]=0;
	}
};
namespace SAM{
	int len[1202000],ch[1202000][27],link[1202000],tot,las,p,q,cle,cur;
	I init(){tot=las=1;}
	I add(int x){
		cur=++tot;len[cur]=len[las]+1;p=las;las=cur;LCT::w[cur]=1;
		while(p&&!ch[p][x])ch[p][x]=cur,p=link[p];
		if(!p){link[cur]=1;LCT::link(cur,1);return;}
		q=ch[p][x];
		if(len[p]+1==len[q]){link[cur]=q;LCT::link(cur,q);return;}
		cle=++tot;len[cle]=len[p]+1,link[cle]=link[q];LCT::link(cle,link[cle]);
		memcpy(ch[cle],ch[q],sizeof(ch[q]));
		LCT::cut(q,link[q]);link[q]=cle;LCT::link(q,link[q]);link[cur]=cle;LCT::link(cur,cle);
		while(p&&ch[p][x]==q)ch[p][x]=cle,p=link[p];
	}
	I insert(){F(i,0,n-1)add(c[i]-'A'+1);}
	I ques(){
		p=1;
		F(i,0,n-1){
			if(!ch[p][c[i]-'A'+1]){
				printf("0\n");return;
			}
			p=ch[p][c[i]-'A'+1];
		}
		LCT::splay(p);
		printf("%d\n",LCT::w[p]);m^=LCT::w[p];
	} 
};
I getit(int x){
	scanf("%s",c);n=strlen(c);
	F(i,0,n-1){
		x=(x*131+i)%n;
		swap(c[i],c[x]);
	}
}
int main(){
	read(Q);m=0;
	scanf("%s",c);
	n=strlen(c);
	SAM::init();
	SAM::insert();
	while(Q--){
		scanf("%s",c+1);
		if(c[1]=='A'){
			getit(m);SAM::insert();
		}
		else{
			getit(m);SAM::ques();
		}
	}
	return 0;
}
posted @ 2020-01-09 08:53  Purple_wzy  阅读(157)  评论(0编辑  收藏  举报