BZOJ 2555: SubString

BZOJ 2555: SubString

标签(空格分隔): OI-BZOJ OI-后缀自动机 OI-LCT


Time Limit: 30 Sec
Memory Limit: 512 MB


Description

懒得写背景了,给你一个字符串init,要求你支持两个操作

(1):在当前字符串的后面插入一个字符串

(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)

你必须在线支持这些操作。

Input

第一行一个数Q表示操作个数

第二行一个字符串表示初始字符串init

接下来Q行,每行2个字符串Type,Str 

Type是ADD的话表示在后面插入字符串。

Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。

为了体现在线操作,你需要维护一个变量mask,初始值为0

此处输入图片的描述

读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result  
插入的时候,将TrueStr插到当前字符串后面即可。

HINT:ADD和QUERY操作的字符串都需要解压

Output

Sample Input

2
A
QUERY B
ADD BBABBBBAAB

Sample Output

0

HINT

40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000

100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000

新加数据一组--2015.05.20


Solution####

给一组自己玩的数据:
10
A
QUERY B
ADD BBABBBBAAB
QUERY AB
ADD BBABBBBAAB
QUERY ABB
ADD BBABBBBAAB
QUERY ABB
ADD BBABBBBAAB
QUERY ABB
ADD BBABBBBAAB

输出
0
3
4
3
6

构造后缀自动机,每个状态的right集合大小即为当前串的出现次数。
用LCT维护自动机的fail树在线得到每个点的right集合大小


Code####

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define PA pair<int,int>
int read()
{
 	int s=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
	return s*f;
}
//smile please
const int N=600005;
struct tree;
extern tree t[N*2];
struct tree
{
	int w[2],f,s,r,la;
	void down()
 	   {
		if(r)swap(w[0],w[1]);
	    if(w[0])t[w[0]].r^=r;
		if(w[1])t[w[1]].r^=r;r=0;
	    s+=la;
	    if(w[0])t[w[0]].la+=la;
	    if(w[1])t[w[1]].la+=la;
		la=0;
	   }
	void updata()
	   {
	   }
}t[N*2];
bool notroot(int x)
{
	return t[t[x].f].w[0]==x||t[t[x].f].w[1]==x;
}
void rotate(int x)
{
	int f=t[x].f,r=(t[f].w[1]==x);
	t[x].f=t[f].f;
	if(notroot(f))
	  t[t[f].f].w[t[t[f].f].w[1]==f]=x;
	t[f].w[r]=t[x].w[!r];
	if(t[x].w[!r])
	  t[t[x].w[!r]].f=f;
	t[f].f=x;
	t[x].w[!r]=f;
	t[f].updata();
}
int sta[N*2];
void splay(int x)
{
	if(x==0)return;
	for(sta[++sta[0]]=x;notroot(sta[sta[0]]);)
	    sta[++sta[0]]=t[sta[sta[0]-1]].f;
 	while(sta[0])t[sta[sta[0]--]].down();
	for(int f;notroot(x);rotate(x))
	    if(notroot(f=t[x].f))
	      rotate(t[t[f].f].w[1]==f^t[f].w[1]==x?x:f);
	t[x].updata();
}
void access(int x){int xx=x;for(int las=0;x;splay(x),t[x].w[1]=las,las=x,x=t[x].f);splay(xx);}
struct samm
{
	int last,total;
	int L[N*2],ch[N*2][26],fa[N*2];//,val[N*2];
	samm(){total=1,last=1;}
	void plu(int x,int s)
	   {//for(;x;x=fa[x])
	    //    val[x]+=s;
	    access(x);t[x].la+=s;
	   }
	void fu(int x,int y)
	   {
	    splay(x),splay(y);
		if(fa[x])
		   {if(t[x].s)plu(fa[x],-t[x].s);
		    access(fa[x]);splay(x);t[x].f=0;
		   }
		t[x].f=y;
		access(x);
		if(t[x].s)
		  plu(y,t[x].s);
		fa[x]=y;
	   }
	void insert(int C)
	   {int p=last,now=last=++total;
	    L[now]=L[p]+1;t[now].s=1;
		for(;p&&!ch[p][C];p=fa[p])
	        ch[p][C]=now;
	    if(!p){fu(now,1);return;}
	    
		if(L[ch[p][C]]==L[p]+1){fu(now,ch[p][C]);return;}
	    
		int ne=++total,Q=ch[p][C];
	    memcpy(ch[ne],ch[Q],sizeof(ch[Q]));
	    fu(ne,fa[Q]);
	    fu(Q,ne);fu(now,ne);
	    L[ne]=L[p]+1;
	    for(;p&&ch[p][C]==Q;p=fa[p])
	        ch[p][C]=ne;
	   }
	int ST(char z[],int len)
	   {int now=1;
	    for(int i=0;i<len;i++)
	        now=ch[now][z[i]-'A'];
	    return now;
	   }
	void print()
	   {
		for(int i=1;i<=total;i++)
	    	printf("%d: f_%d l_%d a_%d b_%d c_%d\n",i,fa[i],L[i],ch[i][0],ch[i][1],ch[i][2]);
	   }
}a;
int len;
char z[3000005];
int Q,mask;
void readstr()
{
	len=0;z[0]=getchar();
	while(z[0]<'A'||z[len]>'Z')z[0]=getchar();
	while(z[len]>='A'&&z[len]<='Z')z[++len]=getchar();
	z[len]=0;
}
void decode(int mask)
{
	for(int i=0;i<len;i++)
	   {mask=(mask*131+i)%len;
	    swap(z[i],z[mask]);
	   }
}
int solve()
{
	int x=a.ST(z,len);
	splay(x);
	return t[x].s;
}
int main()
{
 	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	Q=read();
	readstr();
	for(int i=0;i<len;i++)
	    a.insert(z[i]-'A');
	while(Q--)
	   {readstr();
	    if(z[0]=='A')
	       {readstr();decode(mask);
	   	    for(int i=0;i<len;i++)
	   	        a.insert(z[i]-'A');
		   }
		else
		   {readstr();decode(mask);
	   		int ans=solve();
	   		mask^=ans;
	   		printf("%d\n",ans);
		   }
	   }
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}

posted on 2016-03-18 22:28  wuyuhan  阅读(269)  评论(0编辑  收藏  举报

导航