bzoj 2555: SubString

Description

懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。

Solution

思路比较直观啊
首先没有插入的话,预处理好每个点 \(|right|\) 就好了
如果有插入的话我们发现实际上就是维护一个子树大小
每一次插入一个节点就相当于把父亲到根路径上的权值全部 \(+1\)
我们用 \(LCT\) 维护这个加边删边和路径加法的操作
每一次询问就是先找到这个串对应的节点 \(x\),如果没找到答案就是 \(0\),否则就是 \(|Right_x|\)

这题是有根树,不需要 \(makeroot\) 操作,写起来比较舒服

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
namespace LCT{
	int ch[N][2],fa[N],la[N],w[N];
	inline bool isrt(int x){return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;}
	inline void mark(int x,int t){la[x]+=t;w[x]+=t;}
	inline void pushdown(int x){
		if(!la[x])return ;
		mark(ch[x][0],la[x]);mark(ch[x][1],la[x]);
		la[x]=0;
	}
	inline void rotate(int x){
		int y=fa[x];bool t=ch[y][1]==x;
		ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
		ch[x][!t]=y;fa[x]=fa[y];
		if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
		fa[y]=x;
	}
	inline void Push(int x){
		if(!isrt(x))Push(fa[x]);
		pushdown(x);
	}
	inline void splay(int x){
		Push(x);
		while(!isrt(x)){
			int y=fa[x],p=fa[y];
			if(isrt(y))rotate(x);
			else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
			else rotate(x),rotate(x);
		}
	}
	inline void access(int x){
		int y=0;
		while(x)splay(x),ch[x][1]=y,x=fa[y=x];
	}
	inline void link(int x,int y){
		fa[x]=y;access(y);splay(y);splay(x);mark(y,w[x]);
	}
	inline void cut(int x){
		access(x);splay(x);mark(ch[x][0],-w[x]);fa[ch[x][0]]=0;ch[x][0]=0;
	}
	inline int query(int x){
		splay(x);return w[x];
	}
}
char s[N],op[10];int Q,mask=0;
inline void decode(){
	int len=strlen(s),t=mask;
	for(int j=0;j<len;j++){
		t=(t*131+j)%len;
		swap(s[j],s[t]);
	}
}
int ch[N][27],fa[N],len[N],cur=1,cnt=1;
inline void ins(int c){
	int p=cur;cur=++cnt;len[cur]=len[p]+1;LCT::w[cur]=1;
	for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
	if(!p)fa[cur]=1,LCT::link(cur,1);
	else{
		int q=ch[p][c];
		if(len[q]==len[p]+1)fa[cur]=q,LCT::link(cur,q);
		else{
			int nt=++cnt;len[nt]=len[p]+1;
			memcpy(ch[nt],ch[q],sizeof(ch[q]));
			LCT::cut(q);LCT::link(nt,fa[q]);LCT::link(q,nt);LCT::link(cur,nt);
			fa[nt]=fa[q];fa[q]=fa[cur]=nt;
			for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
		}
	}
}
inline int solve(int len){
	int p=1;
	for(int i=0;i<len;i++){
		int c=s[i]-'A';
		if(ch[p][c])p=ch[p][c];
		else return 0;
	}
	return LCT::query(p);
}
int main(){
	freopen("pp.in","r",stdin);
	freopen("pp.out","w",stdout);
	cin>>Q;
	scanf("%s",s);
	for(int i=0,le=strlen(s);i<le;i++)ins(s[i]-'A');
	while(Q--){
		scanf("%s%s",op,s);
		decode();
		int len=strlen(s),la;
		if(op[0]=='A')for(int i=0;i<len;i++)ins(s[i]-'A');
		else printf("%d\n",la=solve(len)),mask^=la;
	}
	return 0;
}

posted @ 2018-04-13 11:54  PIPIBoss  阅读(166)  评论(0编辑  收藏  举报