zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 2555 SubString

    Description

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

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

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

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

    Input

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

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

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

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

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

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

    读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。

    询问的时候,对TrueStr询问后输出一行答案Result

    然后mask=maskxorResult

    插入的时候,将TrueStr插到当前字符串后面即可。

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

    长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000

    新加数据一组--2015.05.20

    Sample Input

    2

    A

    QUERY B

    ADD BBABBBBAAB

    Sample Output

    0

    Solution

    LCT+SAM

    考虑静态时,一个字符串 (S) 在另一个字符串 (T) 中的出现次数。将 (T) 建出SAM,那么 (S) 出现次数就是先将 (S) 在SAM上匹配,然后匹配完的那个节点的size就是出现次数了。

    那么动态的的话,用LCT维护parent树就好了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=600000+10,MAXM=3000000+10;
    int n,q,ch[MAXN<<1][30],fa[MAXN<<1],len[MAXN<<1],size[MAXN<<1],mask,las=1,tot=1;
    char s[MAXM];
    #define lc(x) ch[(x)][0]
    #define rc(x) ch[(x)][1]
    struct LinkCut_Tree{
    	int sum[MAXN<<1],ch[MAXN<<1][2],fa[MAXN<<1],stack[MAXN<<1],cnt,Isum[MAXN<<1],rev[MAXN<<1];
    	inline bool nroot(int x)
    	{
    		return lc(fa[x])==x||rc(fa[x])==x;
    	}
    	inline void reverse(int x)
    	{
    		std::swap(lc(x),rc(x));
    		rev[x]^=1;
    	}
    	inline void pushup(int x)
    	{
    		sum[x]=sum[lc(x)]+sum[rc(x)]+size[x]+Isum[x];
    	}
    	inline void pushdown(int x)
    	{
    		if(rev[x])
    		{
    			if(lc(x))reverse(lc(x));
    			if(rc(x))reverse(rc(x));
    			rev[x]=0;
    		}
    	}
    	inline void rotate(int x)
    	{
    		int f=fa[x],p=fa[f],c=(rc(f)==x);
    		if(nroot(f))ch[p][rc(p)==f]=x;
    		fa[ch[f][c]=ch[x][c^1]]=f;
    		fa[ch[x][c^1]=f]=x;
    		fa[x]=p;
    		pushup(f);
    		pushup(x);
    	}
    	inline void splay(int x)
    	{
    		cnt=0;
    		stack[++cnt]=x;
    		for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
    		while(cnt)pushdown(stack[cnt--]);
    		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
    			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
    		pushup(x);
    	}
    	inline void access(int x)
    	{
    		for(register int y=0;x;x=fa[y=x])
    		{
    			splay(x);
    			Isum[x]+=sum[rc(x)];
    			rc(x)=y;
    			Isum[x]-=sum[rc(x)];
    			pushup(x);
    		}
    	}
    	inline void makeroot(int x)
    	{
    		access(x);splay(x);reverse(x);
    	}
    	inline void split(int x,int y)
    	{
    		makeroot(x);access(y);splay(y);
    	}
    	inline void link(int x,int y)
    	{
    		makeroot(x);access(y);splay(y);
    		fa[x]=y;
    		Isum[y]+=sum[x];
    		pushup(y);
    	}
    	inline void cut(int x,int y)
    	{
    		split(x,y);
    		fa[x]=lc(y)=0;
    		pushup(y);
    	}
    };
    LinkCut_Tree T;
    #undef lc
    #undef rc
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void extend(int c)
    {
    	int p=las,np=++tot;
    	las=np;
    	len[np]=len[p]+1;size[np]=1;
    	while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
    	if(!p)fa[np]=1,T.link(np,1);
    	else
    	{
    		int q=ch[p][c];
    		if(len[q]==len[p]+1)fa[np]=q,T.link(np,q);
    		else
    		{
    			int nq=++tot;
    			fa[nq]=fa[q];T.link(nq,fa[q]);
    			memcpy(ch[nq],ch[q],sizeof(ch[nq]));
    			len[nq]=len[p]+1;T.cut(q,fa[q]);
    			fa[q]=fa[np]=nq;T.link(q,nq);T.link(np,nq);
    			while(p&&ch[p][c]==q)ch[p][c]=nq,p=fa[p];
    		}
    	}
    }
    inline void decode(int mask)
    {
    	for(register int i=0,lt=strlen(s);i<lt;++i)std::swap(s[i],s[mask=(mask*131+i)%lt]);
    }
    int main()
    {
    	read(q);
    	scanf("%s",s);
    	for(register int i=0,lt=strlen(s);i<lt;++i)extend(s[i]-'A'+1);
    	while(q--)
    	{
    		char opt[8];scanf("%s",opt);scanf("%s",s);
    		decode(mask);
    		if(opt[0]=='A')
    			for(register int i=0,lt=strlen(s);i<lt;++i)extend(s[i]-'A'+1);
    		if(opt[0]=='Q')
    		{
    			int j=1,mark=1;
    			for(register int i=0,lt=strlen(s),c;i<lt;++i)
    			{
    				c=s[i]-'A'+1;
    				if(ch[j][c])j=ch[j][c];
    				else {mark=0;break;}
    			}
    			if(!mark)puts("0");
    			else
    			{
    				T.makeroot(1);T.access(j);
    				write(T.Isum[j]+size[j],'
    ');
    				mask^=(T.Isum[j]+size[j]);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    sqlplus登录用户hang住
    ORACLE_19c用户密码登录失败的问题以及ORA-28040
    索引瘦身_oracle_11g
    Linux内存大页设置
    C++ 总体内容(2)
    C++ 总体内容(1)
    vector中erase的用法
    NGUI中的Tween的委托使用
    IOS Android支持中文与本地文件的读取写入
    Unity人工智能学习—确定性AI算法之追踪算法二
  • 原文地址:https://www.cnblogs.com/hongyj/p/9285809.html
Copyright © 2011-2022 走看看