zoukankan      html  css  js  c++  java
  • BZOJ 2555: SubString

    2555: SubString

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 2556  Solved: 764
    [Submit][Status][Discuss]

    Description

      
        懒得写背景了,给你一个字符串init,要求你支持两个操作
        
        (1):在当前字符串的后面插入一个字符串
        
        (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
        
        你必须在线支持这些操作。
        

    Input

        第一行一个数Q表示操作个数
        
        第二行一个字符串表示初始字符串init
        
        接下来Q行,每行2个字符串Type,Str 
        
        Type是ADD的话表示在后面插入字符串。
        
        Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
        
        为了体现在线操作,你需要维护一个变量mask,初始值为0
       
        
        读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
        询问的时候,对TrueStr询问后输出一行答案Result
        然后mask = mask xor Result  
        插入的时候,将TrueStr插到当前字符串后面即可。

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

    Output

    Sample Input

    2

    A

    QUERY B

    ADD BBABBBBAAB

    Sample Output

    0

    HINT

     40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000
    100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000

    新加数据一组--2015.05.20

    Source

    Ctsc模拟赛By 洁妹

    分析:

    据说是$SAM$的裸题...

    考虑每一次加入一个串就直接增量法建初后缀自动机,每一次询问就在$SAM$上去匹配,找到匹配完成的节点输出$|endpos|$,那么其实这道题的点大概就在于加入一个字符之后如何动态维护每个点的$|endpos|$,考虑加入一个字符,只会让这个字符在$fail$上到根结点的那条路径上的点的$|endpos|$加$1$,所以我们可以用$LCT$来维护每个点的权值,然后每一次要把路径权值$+1$就打个标记...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    using namespace std;
    
    const int maxn=1300000+5;
    
    int n,mask,last=1,tail=1,Max[maxn],Min[maxn],nxt[maxn][26],fail[maxn];
    int son[maxn][2],val[maxn],add[maxn],father[maxn];
    
    char s[maxn],opt[13];
    
    inline bool isroot(int x){
    	if(father[x]==0)
    		return true;
    	int f=father[x];
    	if(son[f][0]==x)
    		return false;
    	if(son[f][1]==x)
    		return false;
    	return true;
    }
    
    inline void pushdown(int x){
    	if(add[x]){
    		if(son[x][0])
    			val[son[x][0]]+=add[x],add[son[x][0]]+=add[x];
    		if(son[x][1])
    			val[son[x][1]]+=add[x],add[son[x][1]]+=add[x];
    		add[x]=0;
    	}
    }
    
    
    inline void push(int t){
    	static int stk[maxn];
    	int top=0;
    	stk[top++]=t;
    	while(!isroot(t))
    		stk[top++]=t=father[t];
    	while(top) pushdown(stk[--top]);
    }
    
    inline void connect(int f,int t,int k){
    	if(t) father[t]=f;
    	if(f) son[f][k]=t;
    }
    
    inline void rotate(int t){
    	int f=father[t];
    	int g=father[f];
    	int s=(son[f][1]==t);
    	connect(f,son[t][!s],s);
    	connect(t,f,!s);
    	father[t]=g;
    	if(g&&son[g][0]==f) son[g][0]=t;
    	if(g&&son[g][1]==f) son[g][1]=t;
    }
    
    inline void splay(int t){
    //	cout<<"splay: "<<t<<endl;
    	push(t);
    	while(!isroot(t)){
    		int f=father[t];
    		int g=father[f];
    		if(isroot(f))
    			rotate(t);
    		else{
    			bool a=(f&&son[f][1]==t);
    			bool b=(g&&son[g][1]==f);
    			if(a==b)
    				rotate(f),rotate(t);
    			else
    				rotate(t),rotate(t);
    		}
    	}
    }
    
    inline void access(int t){
    //	cout<<"access: "<<t<<endl;
    	int p=0,x=t;
    	while(t){
    		splay(t);
    		son[t][1]=p;
    		p=t,t=father[t];
    	}
    	splay(x);
    }
    
    inline void link(int t,int f){
    //	cout<<"link: "<<t<<" "<<f<<endl;
    	splay(t);father[t]=f;
    }
    
    inline void cut(int t){
    //	cout<<"cut: "<<t<<endl;
    	access(t);int x=son[t][0];
    	father[x]=son[t][0]=0;
    }
    
    inline void build(char *s){
    	while(*s){
    		int p=last,t=++tail,c=*s++-'A';
    		Max[t]=Max[p]+1;
    //		cout<<"char: "<<(char)(c+'A')<<endl;
    		while(p&&!nxt[p][c])
    			nxt[p][c]=t,p=fail[p];
    		if(p){
    			int q=nxt[p][c];
    			if(Max[q]==Max[p]+1)
    				fail[t]=q,Min[t]=Max[q]+1;
    			else{
    				int k=++tail;
    				fail[k]=fail[q];
    				fail[q]=fail[t]=k;
    				Max[k]=Max[p]+1;
    				Min[q]=Max[k]+1;
    				Min[t]=Max[k]+1;
    				Min[k]=Max[fail[k]]+1;
    				memcpy(nxt[k],nxt[q],26*sizeof(int));
    				while(p&&nxt[p][c]==q)
    					nxt[p][c]=k,p=fail[p];
    //				puts("hahahahahah");
    				cut(q);link(k,fail[k]),link(q,k);val[k]=val[q];
    			}
    		}
    		else
    			Min[t]=fail[t]=1;
    		last=t;link(t,fail[t]);
    //		puts("finish link");
    		access(t);
    //		puts("finish access");
    		add[t]++,val[t]++;
    	}
    }
    
    inline void decodewithmask(int tmp){
    	int len=strlen(s);
    	for(int i=0;i<len;i++){
    		tmp=(tmp*131+i)%len;
    		swap(s[i],s[tmp]);
    	}
    }
    
    inline int solve(char *s){
    	int u=1;
    	while(*s){
    		int c=*s++-'A';
    		if(nxt[u][c])
    			u=nxt[u][c];
    		else
    			return 0;
    	}
    	access(u);
    	return val[u];
    }
    
    signed main(void){
    //	freopen("SubString1.in","r",stdin);
    	scanf("%d%s",&n,s);
    	build(s);
    	for(int i=1,ans;i<=n;i++){
    		scanf("%s%s",opt,s);decodewithmask(mask);
    //		puts(s);
    		if(opt[0]=='Q')
    			printf("%d
    ",ans=solve(s)),mask^=ans;
    		else
    			build(s);
    	}
    	return 0;
    }
    

      


    $By NeighThon$

  • 相关阅读:
    MVC3分页
    ASP.NET MVC导入excel到数据库,下载文件
    使用JS获取客户端MAC地址
    关于mschart控件在mvc项目中的webform里面显示不出图片的问题
    difference between "on" and "where" when using left/right join query
    Will static methods over multithreading cause threadsafe problem?
    const VS readonly in detail
    一个编码引发js错误的问题
    分享一个基于FileSystemWatcher的文件自动备份程序
    Back/Forward and Refresh in browser
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6736844.html
Copyright © 2011-2022 走看看