zoukankan      html  css  js  c++  java
  • bzoj2555-SubString

    题目

    给出一个初始字符串(s),支持两种操作:

    • 在字符串后面添加一个字符串((s+=t)
    • 询问一个字符串在(s)中出现了几次

    设字符串最终长度为(n),询问次数为(q),询问字符串总长为(m)(nle 6 imes 10^5, qle 10^4, mle 3 imes 10^6)

    分析

    非常简单的题目。添加字符串用后缀自动机实现,并且用link-cut tree维护后缀树,询问一个字符串出现几次的时候,现在自动机上跑到字符串对应的点(p)(如果没有就是无解),再在lct上查询(p)的子树中关键点的个数即可。不需要使用TopTree,只需要在每次加点的时候用lct更新链上的点即可。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long giant;
    const int maxn=6e5+10;
    const int maxl=3e6+10;
    const int maxc=26;
    char s[maxl];
    void decode(char s[],int len,int mask) {
    	for (int j=0;j<len;++j) {
    		mask=(int)((giant)mask*131+j)%len;
    		swap(s[mask],s[j]);
    	}
    }
    struct LCT {
    	struct node {
    		int ch[2],fa,w,sum,size,tag;
    		bool rev;
    		node ():size(1) {}
    	} t[maxn<<1];
    	LCT () {t[0].size=0;}
    	bool isroot(int x) {
    		return !t[x].fa || t[t[x].fa].ch[rson(x)]!=x;
    	}
    	bool rson(int x) {
    		return t[t[x].fa].ch[1]==x;
    	}
    	void update(int x) {
    		t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;
    		t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+t[x].w;
    	}
    	void down(int x) {
    		if (!isroot(x)) down(t[x].fa);
    		if (t[x].tag) {
    			doit(t[x].ch[0],t[x].tag);
    			doit(t[x].ch[1],t[x].tag);
    			t[x].tag=0;
    		}
    		if (t[x].rev) {
    			swap(t[x].ch[0],t[x].ch[1]);
    			if (t[x].ch[0]) t[t[x].ch[0]].rev^=true;
    			if (t[x].ch[1]) t[t[x].ch[1]].rev^=true;
    			t[x].rev=false;
    		}
    	}
    	void rotate(int x) {
    		int f=t[x].fa,d=rson(x),c=t[x].ch[d^1];
    		if (c) t[c].fa=f;
    		if (!isroot(f)) t[t[f].fa].ch[rson(f)]=x;
    		t[x].fa=t[f].fa,t[f].fa=x,t[x].ch[d^1]=f,t[f].ch[d]=c;
    		update(f);
    		update(x);
    	}
    	void splay(int x) {
    		down(x);
    		while (!isroot(x)) if (isroot(t[x].fa)) rotate(x); else {
    			if (rson(x)==rson(t[x].fa)) rotate(x),rotate(x); else 
    			rotate(t[x].fa),rotate(x);
    		}
    	}
    	void access(int x) {
    		for (int last=0;x;x=t[last=x].fa) {
    			splay(x);
    			t[x].ch[1]=last;
    			update(x);
    		}
    	}
    	void makeroot(int x) {
    		access(x);
    		splay(x);
    		t[x].rev^=true;
    	}
    	void link(int x,int y) {
    		makeroot(x);
    		//access(y);
    		t[x].fa=y;
    	}
    	void cut(int x,int y) {
    		makeroot(x);
    		access(y);
    		splay(y);
    		t[y].ch[0]=t[x].fa=0;
    		update(y);
    		update(x);
    	}
    	int query(int x,int y) {
    		makeroot(x);
    		access(y);
    		splay(y);
    		return t[y].sum;
    	}
    	void doit(int x,int w) {
    		t[x].w+=w;
    		t[x].sum+=t[x].size*w;
    		t[x].tag+=w;
    	}
    	void add(int x,int y,int w) {
    		makeroot(x);
    		access(y);
    		splay(y);
    		doit(y,w);
    	}
    } lct;
    struct SAM {
    	int t[maxn<<1][maxc],len[maxn<<1],link[maxn<<1],tot,last;
    	SAM ():tot(1),last(1) {}
    	void add(int c) {
    		int nw=++tot,i;
    		len[nw]=len[last]+1;
    		for (i=last;i && !t[i][c];i=link[i]) t[i][c]=nw; 
    		if (i) {
    			int p=t[i][c];
    			if (len[p]==len[i]+1) link[nw]=p; else {
    				int q=++tot;
    				len[q]=len[i]+1;
    				memcpy(t[q],t[p],sizeof t[p]);
    				for (int j=i;j && t[j][c]==p;j=link[j]) t[j][c]=q;
    				int w=lct.query(p,p);
    				lct.cut(link[p],p);
    				lct.link(link[p],q);
    				lct.link(q,p);
    				lct.add(q,q,w);
    				link[q]=link[p],link[p]=link[nw]=q;
    			}
    		} else link[nw]=1;
    		lct.link(link[nw],nw);
    		lct.add(1,nw,1);
    		last=nw;
    	}
    	int run(char s[],int len) {
    		int now=1;
    		for (int i=0;i<len;++i) now=t[now][s[i]-'A'];
    		if (!now) return 0; 
    		int ret=lct.query(now,now);
    		return ret;
    	}
    } sam;
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	int m,mask=0;
    	scanf("%d",&m);
    	scanf("%s",s);
    	int len=strlen(s);
    	for (int i=0;i<len;++i) sam.add(s[i]-'A');
    	while (m--) {
    		static char ord[10];
    		scanf("%s%s",ord,s);
    		len=strlen(s);
    		decode(s,len,mask);
    		if (ord[0]=='A') for (int i=0;i<len;++i) sam.add(s[i]-'A'); else {
    			int ans=sam.run(s,len);
    			mask^=ans;
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    django系列5.4--ORM中执行原生SQL语句, Python脚本中调用django环境
    Cookie背景了解
    [leetcode] 832. Flipping an Image
    [leetcode] 888. Fair Candy Swap
    [leetcode] 66. Plus One
    0000:Deep Learning Papers Reading Roadmap
    [算法]时间复杂度
    [leetcode] 771. Jewels and Stones
    [cs231n] Convolutional Neural Networks for Visual Recognition
    推翻自己,从头来过
  • 原文地址:https://www.cnblogs.com/owenyu/p/6724640.html
Copyright © 2011-2022 走看看