zoukankan      html  css  js  c++  java
  • [BZOJ2555] SubString

    bzoj

    题意

    给你一个初始模板串,要求资瓷以下两个操作:
    1、在模板串的末尾接上一个串;
    2、查询一个串在模板串中出现了多少次。
    强制在线。

    sol

    末尾添加直接(extend)
    查询一个串的出现次数就是查对应状态的(right)集合大小。
    由于是动态的所以需要用(LCT)维护。相当于是在维护子树信息(子树和)。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 1250000;
    struct lct{
    	int fa[N],ch[2][N],val[N],sum[N];
    	bool son(int x)
    		{
    			return x==ch[1][fa[x]];
    		}
    	bool isroot(int x)
    		{
    			return x!=ch[0][fa[x]]&&x!=ch[1][fa[x]];
    		}
    	void pushup(int x)
    		{
    			sum[x]=val[x]+sum[ch[0][x]]+sum[ch[1][x]];
    		}
    	void rotate(int x)
    		{
    			int y=fa[x],z=fa[y],c=son(x);
    			ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
    			fa[x]=z;if (!isroot(y)) ch[son(y)][z]=x;
    			ch[c^1][x]=y;fa[y]=x;pushup(y);
    		}
    	void splay(int x)
    		{
    			for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
    				if (!isroot(y)) son(x)^son(y)?rotate(x):rotate(y);
    			pushup(x);
    		}
    	void access(int x)
    		{
    			for (int y=0;x;y=x,x=fa[x])
    			{
    				splay(x);val[x]+=sum[ch[1][x]]-sum[y];
    				ch[1][x]=y;pushup(x);
    			}
    		}
    	void link(int x,int y)
    		{
    			splay(x);access(y);splay(y);
    			fa[x]=y;val[y]+=sum[x];pushup(y);
    		}
    	void cut(int x)
    		{
    			access(x);splay(x);
    			ch[0][x]=fa[ch[0][x]]=0;pushup(x);
    		}
    }T;
    int last=1,tot=1,tr[N][26],fa[N],len[N],q,mask,ans;char s[N*3],op[N];
    void extend(int c)
    {
    	int v=last,u=++tot;T.val[last=u]=1;
    	len[u]=len[v]+1;
    	while (v&&!tr[v][c]) tr[v][c]=u,v=fa[v];
    	if (!v) fa[u]=1,T.link(u,1);
    	else{
    		int x=tr[v][c];
    		if (len[x]==len[v]+1) fa[u]=x,T.link(u,x);
    		else{
    			int y=++tot;
    			memcpy(tr[y],tr[x],sizeof(tr[y]));
    			if (fa[x]) T.cut(x),T.link(y,fa[x]);
    			fa[y]=fa[x];fa[x]=fa[u]=y;len[y]=len[v]+1;
    			T.link(x,y);T.link(u,y);
    			while (v&&tr[v][c]==x) tr[v][c]=y,v=fa[v];
    		}
    	}
    }
    void decode(int l)
    {
    	for (int i=0,tmp=mask;i<l;++i)
    		tmp=(tmp*131+i)%l,swap(s[i],s[tmp]);
    }
    int main()
    {
    	scanf("%d %s",&q,s);int l=strlen(s);
    	for (int i=0;i<l;++i) extend(s[i]-'A');
    	while (q--){
    		scanf(" %s %s",op,s);l=strlen(s);
    		decode(l);
    		if (op[0]=='Q')
    		{
    			int now=1;
    			for (int i=0;i<l;++i) now=tr[now][s[i]-'A'];
    			if (!now) ans=0;
    			else T.access(now),T.splay(now),ans=T.val[now];
    			printf("%d
    ",ans);mask^=ans;
    		}
    		else for (int i=0;i<l;++i) extend(s[i]-'A');
    	}
    	return 0;
    }
    
  • 相关阅读:
    GDAL创建JPG或PNG格式图像
    GDAL从二进制数据流中构造数据集
    curl使用小记(三)——获取远端数据到内存缓冲区
    C++产生N以内的随机整数
    搬迁声明
    C++通过文件指针获取文件大小
    大地经纬度坐标系与Web墨卡托坐标系的转换
    计算机体系结构基础
    网站设置为禁止粘贴、复制和另存
    区块链交易隐私如何保证?华为零知识证明技术实战解析
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8921975.html
Copyright © 2011-2022 走看看