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;
    }
    
  • 相关阅读:
    内存泄漏 Memory Leaks 内存优化 MD
    Handler Thread 内部类引起内存泄露分析
    为什么不取消注册BroadcastReceiver会导致内存泄漏
    WebChromeClient 简介 API 案例
    WebViewClient 简介 API 案例
    java.net.URI 简介 文档 API
    android.net.Uri 简介 API
    RV 多样式 MultiType 聊天界面 消息类型 MD
    JS函数声明与定义,作用域,函数声明与表达式的区别
    CSS中table tr:nth-child(even)改变tr背景颜色: IE7,8无效
  • 原文地址:https://www.cnblogs.com/owenyu/p/6724640.html
Copyright © 2011-2022 走看看