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

    SAM+LCT维护parent tree版本

    虽然说子树维护那套理论需要ETT

    不过parent tree的根是固定的,所以用lct加一些奇怪的乱搞就行了

    //随手拖个SAM的板子和LCT的板子,然后再加几句话就写完了【手动滑稽

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #define ll long long
    #define N 1200006
    
    using namespace std;
    struct LinkCutTree{
    	#define ls(a) (t[a].c[0])
    	#define rs(a) (t[a].c[1])
    	struct LCTnode{
    		int c[2],fa;
    		int sum,tag;
    	} t[N];
    	void newnode(int x,int value){
    		ls(x)=rs(x)=t[x].fa=t[x].tag=0;
    		t[x].sum=value;
    	}
    	void Add(int x,int delta){
    		if (!x) return;
    		t[x].sum+=delta;t[x].tag+=delta;
    	}
    	int f(int x){return (ls(t[x].fa)!=x)*(1-2*(rs(t[x].fa)!=x));}
    	void PushDown(int x){
    		if (t[x].tag){
    			Add(ls(x),t[x].tag);
    			Add(rs(x),t[x].tag);
    			t[x].tag=0;
    		}
    	}
    	void rotate(int x){
    		int y=t[x].fa,z=t[y].fa,k=f(x),fz=f(y);
    		if (fz>=0) t[z].c[fz]=x;
    		t[y].c[k]=t[x].c[k^1];t[x].c[k^1]=y;
    		t[t[y].c[k]].fa=y;t[x].fa=z;t[y].fa=x;
    	}
    	int stack[N],top;
    	void splay(int x){
    		top=0;stack[top++]=x;
    		for (int i=x;f(i)>=0;i=t[i].fa) stack[top++]=t[i].fa;
    		while (top) PushDown(stack[--top]);
    		for (;f(x)>=0;rotate(x))
    			if (f(t[x].fa)==f(x)) rotate(t[x].fa);
    			else if (f(t[x].fa)>=0) rotate(x);
    	}
    	void access(int x){
    		for (int son=0;x;son=x,x=t[x].fa)
    			splay(x),rs(x)=son;
    	}
    	void link(int u,int f){
    		access(f);splay(f);Add(f,t[u].sum);
    		t[u].fa=f;
    	}
    	void cut(int u){
    		access(u);splay(u);Add(ls(u),-t[u].sum);
    		ls(u)=t[ls(u)].fa=0;
    	}
    	int getsum(int u){
    		splay(u);return t[u].sum;
    	}
    } pt;
    
    struct SAM{
    	struct SAMnode{
    		int par,mx,go[26];
    		SAMnode(){}
    		SAMnode(int _mx):par(0),mx(_mx){
    			memset(go,0,sizeof(go));
    		}
    	} t[N];
    	int last,size;
    	int newnode(int _mx,int value){
    		t[++size]=SAMnode(_mx);
    		pt.newnode(size,value);
    		return size;
    	}
    	void clear(){size=0;last=newnode(0,0);}
    	void extend(char c){
    		c-='A';
    		int p=last,np=newnode(t[p].mx+1,1);
    		for (;p&&!t[p].go[c];p=t[p].par) t[p].go[c]=np;
    		if (!p) t[np].par=1,pt.link(np,1);
    		else{
    			int q=t[p].go[c];
    			if (t[p].mx+1==t[q].mx) t[np].par=q,pt.link(np,q);
    			else{
    				int nq=newnode(t[p].mx+1,0);
    				memcpy(t[nq].go,t[q].go,sizeof(t[q].go));
    				t[nq].par=t[q].par;pt.link(nq,t[q].par);
    				t[np].par=nq;pt.link(np,nq);
    				pt.cut(q);t[q].par=nq;pt.link(q,nq);
    				for (;p&&t[p].go[c]==q;p=t[p].par) t[p].go[c]=nq;
    			}
    		}
    		last=np;
    	}
    	int solve(char *s){
    		int p=1;
    		for (int i=0;p&&s[i];++i) p=t[p].go[s[i]-'A'];
    		if (!p) return 0;
    		return pt.getsum(p);
    	}
    } sam;
    
    void decode(char *s,int mask){
    	int l=strlen(s);
    	for (int i=0;i<l;++i){
    		mask=(mask*131+i)%l;
    		swap(s[i],s[mask]);
    	}
    }
    
    char st[N],op[10];
    int main(){
    	int Q;scanf("%d%s",&Q,st);
    	sam.clear();
    	for (int i=0;st[i];++i) sam.extend(st[i]);
    	int mask=0,res;
    	while (Q--){
    		scanf("%s%s",op,st);
    		decode(st,mask);
    		if (op[0]=='Q'){
    			printf("%d
    ",res=sam.solve(st));
    			mask^=res;
    		}
    		else for (int i=0;st[i];++i) sam.extend(st[i]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    RabbitMQ 路由选择 (Routing)
    RabbitMQ 发布/订阅
    RabbitMQ 工作队列
    MySQL中的insert ignore into, replace into等的一些用法总结
    BigDecimal用法详解
    RabbitMQ 入门 Helloworld
    git标签
    git查看提交历史
    RabbitMQ简介
    【计算机视觉】SeetaFace Engine开源C++人脸识别引擎
  • 原文地址:https://www.cnblogs.com/wangyurzee7/p/5326025.html
Copyright © 2011-2022 走看看