zoukankan      html  css  js  c++  java
  • 【bzoj2555】 SubString

    http://www.lydsy.com/JudgeOnline/problem.php?id=2555 (题目链接)

    题意

      给出一个初始串,维护两个操作。在原串后面加入一个字符串;询问某个字符串在原串中出现的次数。强制在线。

    Solution

      对于加入操作,我们动态构造后缀自动机,每次就将添加的节点${parent}$树上到根节点的路径上的节点的${right}$集合大小全部加${1}$。树上路径区间加法,有因为这是个动态树,所以我们用${LCT}$维护${parent}$树就可以了。

    细节

      坑死了,解码过程中${mask}$是不变的,只有在询问之后才会异或上答案发生改变。幸好看了${PoPoQQQ}$大爷的博客→_→

    代码

    // bzoj2555
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #define RG register
    #define LL long long
    #define inf (1ll<<30)
    #define MOD 1000000007
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=600010,maxm=3000010;
    char s[maxm];
    int Q,mask,r[maxn<<1];
    
    namespace LCT {
    	int tr[maxn<<1][2],fa[maxn<<1],tag[maxn<<1];
    	
    	void pushdown(int x) {
    		if (tr[fa[x]][0]==x || tr[fa[x]][1]==x) pushdown(fa[x]);
    		if (tag[x]) {
    			r[tr[x][0]]+=tag[x];tag[tr[x][0]]+=tag[x];
    			r[tr[x][1]]+=tag[x];tag[tr[x][1]]+=tag[x];
    			tag[x]=0;
    		}
    	}
    	void rotate(int x) {
    		int y=fa[x],z=fa[y],l,r;
    		l=tr[y][1]==x;r=l^1;
    		if (tr[z][0]==y || tr[z][1]==y) tr[z][tr[z][1]==y]=x;
    		fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
    		tr[y][l]=tr[x][r];tr[x][r]=y;
    	}
    	void splay(int x) {
    		pushdown(x);
    		while (tr[fa[x]][0]==x || tr[fa[x]][1]==x) {
    			int y=fa[x],z=fa[y];
    			if (tr[z][0]==y || tr[z][1]==y) {
    				if (tr[z][0]==y ^ tr[y][0]==x) rotate(x);
    				else rotate(y);
    			}
    			rotate(x);
    		}
    	}
    	void access(int x) {
    		for (int y=0;x;y=x,x=fa[x])
    			splay(x),tr[x][1]=y;
    	}
    	void add(int x,int val) {
    		r[x]+=val;tag[x]+=val;
    	}
    	void link(int x,int y) {
    		access(y);splay(y);add(y,r[x]);
    		fa[x]=y;
    	}
    	void cut(int x) {
    		access(x);splay(x);add(tr[x][0],-r[x]);
    		tr[x][0]=fa[tr[x][0]]=0;
    	}
    	int query(int x) {
    		splay(x);return r[x];
    	}
    }
    using namespace LCT;
    
    namespace SAM {
    	int Dargen,last,sz;
    	int len[maxn<<1],ch[maxn<<1][26],par[maxn<<1];
    	void Init() {Dargen=last=sz=1;}
    	void Extend(int c) {
    		int np=++sz,p=last;last=np;
    		len[np]=len[p]+1;r[np]=1;
    		for (;p && !ch[p][c];p=par[p]) ch[p][c]=np;
    		if (!p) par[np]=Dargen,link(np,Dargen);
    		else {
    			int q=ch[p][c];
    			if (len[p]+1==len[q]) par[np]=q,link(np,q);
    			else {
    				int nq=++sz;len[nq]=len[p]+1;
    				memcpy(ch[nq],ch[q],sizeof(ch[q]));
    				par[nq]=par[q],link(nq,par[q]);
    				par[np]=par[q]=nq;
    				cut(q),link(np,nq),link(q,nq);
    				for (;p && ch[p][c]==q;p=par[p]) ch[p][c]=nq;
    			}
    		}
    	}
    	int match(char *r) {
    		int p=Dargen,l=strlen(r);
    		for (int i=0;i<l;i++) {
    			if (!ch[p][r[i]-'A']) return 0;
    			p=ch[p][r[i]-'A'];
    		}
    		return query(p);
    	}
    }
    using namespace SAM;
    
    void decode(char *r,int t) {
    	int len=strlen(r);
    	for (int j=0;j<len;j++) {
    		t=(t*131+j)%len;
    		swap(r[j],r[t]);
    	}
    }
    int main() {
    	scanf("%d",&Q);
    	scanf("%s",s+1);
    	Init();
    	int n=strlen(s+1);
    	for (int i=1;i<=n;i++) Extend(s[i]-'A');
    	char ch[10];mask=0;
    	while (Q--) {
    		scanf("%s%s",ch,s);
    		decode(s,mask);
    		n=strlen(s);
    		if (ch[0]=='A') for (int i=0;i<n;i++) Extend(s[i]-'A');
    		if (ch[0]=='Q') {
    			int ans=match(s);
    			mask^=ans;
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    非常抱歉,全站内容审核中...
    jS代码总结(2)
    timestamp(数据库中的数据类型)
    jS代码总结(1)
    TextWriterTraceListener 和设计时属性支持文件xmta
    validating和validated的区别
    IoC和控制反转
    wince BindingSource
    简单网络传递加密数据
    C#不对称加密
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6389932.html
Copyright © 2011-2022 走看看