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

    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=2555
    题解:

    后缀自动机+LCT
    不难发现,对于输入的询问串,在自动机里trans后的到的状态的Right集合的大小就是答案。
    那么后缀自动机本身就是支持在线添加的,问题就是如何维护好parent树,即如何维护好每个状态的Right集合。
    那么Link-Cut-Tree就显然可以完成动态维护parent树的任务。
    (这里是维护的一颗根固定的树,没有Beroot()等换根函数)

    代码:

    #include<bits/stdc++.h>
    #define MAXN 600005
    using namespace std;
    int MASK;
    struct LCT{
    	int size;
    	int ch[MAXN*3][2],fa[MAXN*3],lazy[MAXN*3],val[MAXN*3];
    	bool Who(int x){return ch[fa[x]][0]!=x;}
    	bool Isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    	void Update(int x,int v){val[x]+=v; lazy[x]+=v;}
    	void Pushdown(int x){
    		if(!Isroot(x)) Pushdown(fa[x]);
    		if(!lazy[x]) return;
    		Update(ch[x][0],lazy[x]);
    		Update(ch[x][1],lazy[x]);
    		lazy[x]=0;
    	}
    	void Rotate(int x){
    		static int y,z,l1,l2;
    		y=fa[x]; z=fa[y];
    		l1=Who(y); l2=Who(x); fa[x]=z;
    		if(!Isroot(y)) ch[z][l1]=x;
    		fa[y]=x; fa[ch[x][l2^1]]=y;
    		ch[y][l2]=ch[x][l2^1]; ch[x][l2^1]=y;
    	}
    	void Splay(int x){
    		static int y; Pushdown(x);
    		for(;y=fa[x],!Isroot(x);Rotate(x)) if(!Isroot(y))
    			Rotate(Who(y)==Who(x)?y:x);
    	}
    	void Access(int x){
    		static int y;
    		for(y=0;x;y=x,x=fa[x])
    			Splay(x),ch[x][1]=y;
    	}
    	void Link(int x,int y){
    		Access(x); Splay(x); Update(x,val[y]); fa[y]=x; 
    	}
    	void Cut(int x){
    		Access(x);
    		Splay(x); 
    		Update(ch[x][0],-val[x]); 
    		fa[ch[x][0]]=0; ch[x][0]=0;
    	}
    	int Query(int x){
    		Splay(x); return val[x];
    	}
    }DT;
    struct SAM{
    	int size,last;
    	int maxs[MAXN*3],trans[MAXN*3][26],parent[MAXN*3];
    	int Newnode(int a,int b){
    		++size; maxs[size]=a;
    		memcpy(trans[size],trans[b],sizeof(trans[b]));
    		return size;
    	}
    	void Extend(int x){
    		static int p,np,q,nq;
    		p=last; last=np=Newnode(maxs[p]+1,0);
    		for(;p&&!trans[p][x];p=parent[p]) trans[p][x]=np;
    		if(!p) parent[np]=1;
    		else{
    			q=trans[p][x];
    			if(maxs[p]+1!=maxs[q]){
    				nq=Newnode(maxs[p]+1,q);
    				parent[nq]=parent[q];
    				parent[q]=parent[np]=nq;
    				for(;p&&trans[p][x]==q;p=parent[p]) trans[p][x]=nq;
    				DT.Cut(q);
    				DT.Link(parent[nq],nq);
    				DT.Link(nq,q);
    			}
    			else parent[np]=q;
    		}
    		DT.val[np]=1;
    		DT.Link(parent[np],np);
    	}
    	void Reset(){
    		memset(trans[0],0,sizeof(trans[0]));
    		size=0; last=Newnode(0,0);
    	}
    	void Add(char *S){
    		for(int i=0;S[i];i++) Extend(S[i]-'A');
    	}
    	void Query(char *T){
    		static int p,ans; p=1;
    		for(int i=0;T[i];i++){
    			if(!trans[p][T[i]-'A']){
    				p=0; break;
    			}
    			p=trans[p][T[i]-'A'];
    		}
    		if(!p) ans=0;
    		else ans=DT.Query(p);
    		printf("%d
    ",ans);
    		MASK^=ans;
    	}
    }SUF;
    void decode(char *S,int mask){
    	static int len; len=strlen(S);
    	for(int i=0;i<len;i++)
    		mask=(mask*131+i)%len,swap(S[i],S[mask]);
    }
    int main(){
    	static char S[MAXN*5],Type[10];
    	int Q; scanf("%d",&Q);
    	SUF.Reset(); 
    	scanf("%s",S); 
    	SUF.Add(S);
    	while(Q--){
    		scanf("%s%s",Type,S);
    		decode(S,MASK);
    		if(Type[0]=='A') SUF.Add(S);
    		else SUF.Query(S);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    vim常用命令
    MYSQL用户管理
    RPM 命令
    Windows下使用xShell向远程Linux上传文件
    Linux PHP 安装过程出现的错误
    完整的 http 错误代码含义解释
    Linux gzip压缩输出
    高性能Mysql主从架构的复制原理及配置详解
    Mybatis多个参数传值方法
    jsp 九大内置对象和其作用详解
  • 原文地址:https://www.cnblogs.com/zj75211/p/8541777.html
Copyright © 2011-2022 走看看