BZOJ2555 Substring

传送门

样例毒瘤 强制在线毒瘤(

做法比较显然啦 我们需要维护一个SAM 并资磁查询子树大小

由于强制在线 所以就需要LCT咯

查询子树大小我们可以变成链加+单点查询

然后匹配过程就和ACA的跳跳跳一样啦

 decode这个地方真的坑 mask要设局部变量

附代码。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define fa(x) t[x].fa
#define not_root(x) (ls(fa(x))==x||rs(fa(x))==x)
#define inf 20021225
#define ll long long
#define mxn 600000
using namespace std;

struct node{int fa,son[26],val,tag;};
struct tree
{
	node t[mxn*4];
	void pushdown(int x)
	{
		if(!x)	return;
		if(t[x].tag)
		{
			int tag=t[x].tag;
			if(ls(x))	t[ls(x)].val+=tag,t[ls(x)].tag+=tag;
			if(rs(x))	t[rs(x)].val+=tag,t[rs(x)].tag+=tag;
			t[x].tag=0;
		}
	}
	void pushup(int x)
	{
		if(!x)	return;
		t[x].val=t[ls(x)].val+t[rs(x)].val;
	}
	void rotate(int x)
	{
		if(!not_root(x)||!x)	return;
		int f=fa(x),gf=fa(f);
		int k=rs(f)==x,p=k^1;
		if(not_root(f))	t[gf].son[rs(gf)==f]=x;
		t[x].fa=gf;t[f].fa=x;
		if(t[x].son[p])	t[t[x].son[p]].fa=f;
		t[f].son[k]=t[x].son[p];
		t[x].son[p]=f;
	}
	void push(int x)
	{
		if(not_root(x))	push(fa(x));
		pushdown(x);
	}
	void splay(int x)
	{
		push(x);
		while(not_root(x))
		{
			int f=t[x].fa,gf=t[f].fa;
			if(not_root(f))
				(rs(f)==x)^(rs(gf)==f)?rotate(x):rotate(f);
			rotate(x);
		}
	}
	void access(int x)
	{
		int y=0;
		do
		{
			splay(x);
			t[x].son[1]=y;
			y=x;x=t[x].fa;
		}while(x);
	}
	void link(int x,int y) // link x to y
	{
		t[x].fa=y; access(y); splay(y); t[y].tag+=t[x].val; t[y].val+=t[x].val;
	}
	void cut(int x)// cut x
	{
		access(x); splay(x);
		t[ls(x)].tag-=t[x].val; t[ls(x)].val-=t[x].val;
		t[ls(x)].fa=0; t[x].son[0]=0;
	}
}lct;
struct point{int len,fa,ch[2];};
struct sam
{
	point pt[mxn*4];
	int rt,poi,lt;
	void insert(int c)
	{
		int p=lt,np=lt=++poi; pt[np].len=pt[p].len+1;
		lct.t[np].val=1;
		for(; p&& !pt[p].ch[c];p=pt[p].fa)	pt[p].ch[c]=np;
		if(!p){lct.link(np,rt);pt[np].fa=rt;return;}
		int q=pt[p].ch[c];
		if(pt[q].len==pt[p].len+1){lct.link(np,q);pt[np].fa=q;return;}
		int nq=++poi; pt[nq].len=pt[p].len+1;
		memcpy(pt[nq].ch,pt[q].ch,sizeof(pt[q].ch));
		lct.cut(q); pt[nq].fa=pt[q].fa; lct.link(nq,pt[q].fa);
		pt[q].fa=pt[np].fa=nq; lct.link(q,nq); lct.link(np,nq);
		for(;p&&pt[p].ch[c]==q;p=pt[p].fa)	pt[p].ch[c]=nq;
	}
	void init()
	{
		rt=lt=++poi;
	}
	void build(char s[])
	{int n=strlen(s);
		for(int i=0;i<n;i++)	insert(s[i]-'A');
	}
	int getans(char s[])
	{
		int pos=rt;int n=strlen(s);
		for(int i=0;i<n;i++)
		{
			if(pt[pos].ch[s[i]-'A'])	pos=pt[pos].ch[s[i]-'A'];
			else	return 0;
		}
		//printf("QAQ");
		lct.access(pos); lct.splay(pos); return lct.t[pos].val;
	}
}sam;
char s[mxn];
void decodewithMask(int mask)
{
	int n=strlen(s);
	for(int i=0;i<n;i++)
	{
		mask=(mask*131+i)%n;
		swap(s[i],s[mask]);
	}
}
char cz[10];
int main()
{
	int q,mask=0,ans=0;
	//freopen("2.in","r",stdin);
	scanf("%d",&q);
	scanf("%s",s);sam.init();sam.build(s);
	for(int i=0;i<q;i++)
	{
		scanf("%s",cz);
		scanf("%s",s);
		decodewithMask(mask);
		if(cz[0]=='A')	sam.build(s);
		else	ans=sam.getans(s),printf("%d\n",ans),mask^=ans;
	}
	return 0;
}
/**
2
AB
ADD BBABB
QUERY BB
*/

 

posted @ 2018-12-20 08:54  寒雨微凝  阅读(127)  评论(0编辑  收藏  举报