码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ2555]SubString

时间:2018-03-07 21:54:05      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:play   一个   stdio.h   lin   include   main   scan   har   int   

考虑在extend($x$)的时候维护SAM中所有串出现的次数,存在每个节点上

在$S$的尾部加入一个字符$x$,只有($S$的后缀+$x$)这种串会多出现一次,所以extend完之后把$np$在parent树中的所有祖先答案$+1$

在extend的过程中只有常数次切换$parent$,相应维护即可

我们要维护parent树,支持link,cut,链增值,点查询,写个lct就好了

糟心...xsy上就是过不了

#include<stdio.h>
#include<string.h>
#define N 1200010
struct lct{
	int fa[N],ch[N][2],v[N],d[N],stk[N];
	#define ls ch[x][0]
	#define rs ch[x][1]
	void ad(int x,int f){
		v[x]+=f;
		d[x]+=f;
	}
	void pushdown(int x){
		if(d[x]){
			if(ls)ad(ls,d[x]);
			if(rs)ad(rs,d[x]);
			d[x]=0;
		}
	}
	void rot(int x){
		int y,z,f,b;
		y=fa[x];
		z=fa[y];
		f=(ch[y][0]==x);
		b=ch[x][f];
		fa[x]=z;
		fa[y]=x;
		if(b)fa[b]=y;
		ch[x][f]=y;
		ch[y][f^1]=b;
		if(ch[z][0]==y)ch[z][0]=x;
		if(ch[z][1]==y)ch[z][1]=x;
	}
	bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
	void gao(int x){
		int t=0;
		while(!isrt(x)){
			t++;
			stk[t]=x;
			x=fa[x];
		}
		t++;
		stk[t]=x;
		for(;t;t--)pushdown(stk[t]);
	}
	void splay(int x){
		int y,z;
		gao(x);
		while(!isrt(x)){
			y=fa[x];
			z=fa[y];
			if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x);
			rot(x);
		}
	}
	void access(int x){
		int y=0;
		while(x){
			splay(x);
			rs=y;
			y=x;
			x=fa[x];
		}
	}
	void add(int y,int f){
		access(y);
		splay(y);
		ad(y,f);
	}
	void link(int x,int y){
		if(x==0||y==0)return;
		fa[x]=y;
		add(y,v[x]);
	}
	void cut(int x){
		access(x);
		splay(x);
		ad(ls,-v[x]);
		fa[ls]=0;
		ls=0;
	}
}l;
struct sam{
	int ch[26],fa,v;
}t[N];
int M=1,las=1;
void extend(int c){
	int p=las,np=++M,q,nq;
	t[np].v=t[p].v+1;
	while(p&&t[p].ch[c]==0){
		t[p].ch[c]=np;
		p=t[p].fa;
	}
	if(p==0){
		t[np].fa=1;
		l.link(np,1);
	}else{
		q=t[p].ch[c];
		if(t[q].v==t[p].v+1){
			t[np].fa=q;
			l.link(np,q);
		}else{
			nq=++M;
			t[nq]=t[q];
			l.link(nq,t[q].fa);
			t[nq].v=t[p].v+1;
			l.cut(q);
			t[np].fa=t[q].fa=nq;
			l.link(q,nq);
			l.link(np,nq);
			while(p&&t[p].ch[c]==q){
				t[p].ch[c]=nq;
				p=t[p].fa;
			}
		}
	}
	las=np;
	l.add(np,1);
}
char s[N];
void decode(int mask){
	int i,n;
	char c;
	n=strlen(s);
	for(i=0;i<n;i++){
		mask=(mask*131+i)%n;
		c=s[i];
		s[i]=s[mask];
		s[mask]=c;
	}
}
void insert(){
	for(int i=0;s[i];i++)extend(s[i]-‘A‘);
}
int query(){
	int i,p;
	for(i=0,p=1;s[i];i++){
		s[i]-=‘A‘;
		if(t[p].ch[s[i]]==0)return 0;
		p=t[p].ch[s[i]];
	}
	l.gao(p);
	return l.v[p];
}
int main(){
	int m,res,mask=0;
	char ch[10];
	scanf("%d%s",&m,s);
	insert();
	while(m--){
		scanf("%s%s",ch,s);
		decode(mask);
		if(ch[0]==‘A‘)
			insert();
		else{
			res=query();
			printf("%d\n",res);
			mask^=res;
		}
	}
}

[BZOJ2555]SubString

标签:play   一个   stdio.h   lin   include   main   scan   har   int   

原文地址:https://www.cnblogs.com/jefflyy/p/8524972.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!