zoukankan      html  css  js  c++  java
  • BZOJ4545: DQS的trie

    题解:  在trie树上构造SAM 首先对于操作1  我们可以边加入边维护答案 通过增减dis[x]-dis[fa[i]]来得到 对于操作二 直接dfs建树即可 和原本构造trie树一样 对于操作三 用LCT维护 具有'价值'节点出现的次数 这个用LCT维护子树信息可以达到 然后就解决问题了

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=3e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t;char v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y,char ch){o->t=y;o->v=ch;o->next=h[x];h[x]=o++;}
    ll read(){
    	ll x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    char str[MAXN];
    int ch[MAXN][2],pre[MAXN],key[MAXN],vis[MAXN];//size zong sz xu
    ll size[MAXN],sz[MAXN];
    bool rt[MAXN],pis[MAXN];
    int cur,cnt,n,m;
    ll ans;
    void newnode(int x){size[x]=key[x]=sz[x]=ch[x][0]=ch[x][1]=0;pre[x]=0;rt[x]=1;}
    void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+sz[x]+key[x];}
    void rotate(int x,int kind){
    	int y=pre[x];
    	pre[ch[x][kind]]=y;ch[y][!kind]=ch[x][kind];
    	if(rt[y])rt[x]=1,rt[y]=0;
    	else ch[pre[y]][ch[pre[y]][1]==y]=x;
    	pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
    	up(y);
    }
    void splay(int x){
    	while(!rt[x]){
    		if(rt[pre[x]])rotate(x,ch[pre[x]][0]==x);
    		else{
    			int y=pre[x];int kind=ch[pre[y]][0]==y;
    			if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
    			else rotate(y,kind),rotate(x,kind);
    		}
    	}
    	up(x);
    }
    void access(int x){
    	int y=0;
    	while(x){
    		splay(x);
    		if(ch[x][1])pre[ch[x][1]]=x,rt[ch[x][1]]=1,sz[x]+=size[ch[x][1]];
    		if(y)rt[y]=0,sz[x]-=size[y];
    		ch[x][1]=y;up(x);
    		y=x;x=pre[x];
    	}
    }
    void destory(int u,int v){access(u);splay(v);ch[v][1]=pre[u]=0;rt[u]=1;up(v);}
    void Link(int u,int v){
    	access(u);splay(u);
    	access(v);
    	splay(v);
    	pre[u]=v;sz[v]+=size[u];
    }
    ll querty(int u){
    	access(u);splay(u);
    	return size[u]-size[ch[u][0]];
    }
    int dis[MAXN],ch0[MAXN][26],fa[MAXN],f[MAXN];
    int built(int x){
    	int last=cur;cur=++cnt;int p=last;dis[cur]=dis[p]+1;newnode(cur);size[cur]=key[cur]=1;
    	for(;p&&!ch0[p][x];p=fa[p])ch0[p][x]=cur;
    	if(!p)fa[cur]=1,Link(cur,1),ans+=dis[cur]-dis[fa[cur]];
    	else{
    		int q=ch0[p][x];
    		if(dis[q]==dis[p]+1)fa[cur]=q,Link(cur,q),ans+=dis[cur]-dis[q];
    		else{
    			int nt=++cnt;dis[nt]=dis[p]+1;newnode(nt);
    			memcpy(ch0[nt],ch0[q],sizeof(ch0[q]));
    			destory(q,fa[q]);ans-=dis[q]-dis[fa[q]];
    			fa[nt]=fa[q];Link(nt,fa[q]);ans+=dis[nt]-dis[fa[nt]];
    			fa[q]=fa[cur]=nt;Link(q,nt);Link(cur,nt);ans+=dis[q]-dis[nt];ans+=dis[cur]-dis[nt];
    			for(;ch0[p][x]==q;p=fa[p])ch0[p][x]=nt;
    		}
    	}
    	return cur;
    }
    void dfs(int x,int pre){
    	f[x]=pre;
    	link(x){
    		if(j->t!=pre&&!pis[j->t]){
    			pis[j->t]=1;cur=vis[x];vis[j->t]=built(j->v-'a');
    			dfs(j->t,x);
    		}
    	}
    }
    ll slove(){
    	scanf("%s",str);int len=strlen(str);
    	int temp=1;
    	for(int i=0;i<len;i++){
    		int t=str[i]-'a';
    		if(!ch0[temp][t])return 0;
    		temp=ch0[temp][t];
    	}
    	return querty(temp);
    }
    int main(){
    	read();vis[1]=1;newnode(1);cur=cnt=1;n=read();char ch;int u,v;ans=0;
    	inc(i,1,n-1)u=read(),v=read(),scanf(" %c",&ch),add(u,v,ch),add(v,u,ch);
    	dfs(1,0);
    	m=read();int op,Rt,num;
    	while(m--){
    		op=read();
    		if(op==1)printf("%lld
    ",ans);
    		else if(op==2){
    			Rt=read();num=read();
    			inc(i,1,num-1)u=read(),v=read(),scanf(" %c",&ch),add(u,v,ch),add(v,u,ch);
    			dfs(Rt,f[Rt]);
    		}
    		else printf("%lld
    ",slove());
    	}
    }
    

     

    4545: DQS的trie

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 248  Solved: 90
    [Submit][Status][Discuss]

    Description

    DQS的自家阳台上种着一棵颗粒饱满、颜色纯正的trie。
    DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符。并且,它拥有极强的生长力:某个i时刻,某个节点就会新生长出一颗子树,它拥有si个节点且节点之间的边上有一个字符,并且新生长出来的子树也是一个树结构。然而因为是新长出来的,根据生活常识可知si必定不会大于i时刻之前的树的大小。
    DQS定义trie的子串为从根节点(1号节点)往下走到所有节点所构成的字符串的所有的后缀。DQS身为一个单身doge,常常取出其中一个子串送给妹子,然而他并不希望送给妹子两个相同的子串,所以他非常关心当前trie的本质不同的子串数目。
    DQS有时还会去商店购买子串,若他在商店看上某个子串,他希望得知这个子串是否在自家阳台的trie上已经出现,若出现则出现了多少次。如果出现了,他就可以直接回家取trie上的子串辣!
    然而DQS身为一个蒟蒻,看着自家阳台的trie树一天天在长大,他被如此众多的节点弄得眼花缭乱,于是他找到了IOI2016Au的你。他会告诉你自家trie树的成长历程,他希望你能够对于每一次询问都做出正确回复。
     

    Input

    第一行输入一个整数id,代表测试点编号。
    接下来一行输入一个整数n0,表示初始树的大小。
    接下来n0-1行,每行两个整数u,v和一个字符c,表示u号节点和v号节点之间有一条边,边上的字母为c。
    接下来输入m表示有m组操作。
    对于每一组,第一行输入一个整数opt。
    若opt=1,则是一组询问,询问当前trie的本质不同的子串数目是多少。
    若opt=2,则后面跟两个整数rt,si,表示以点rt为根向下长出一个子树,大小为si。
    接下来si-1行,每行两个整数u,v和一个字符c,表示u号节点和v号节点之间有一条边,边上的字母为c。若长出子树之前当前树的大小是n,则这si-1点的编号分别为n+1,n+2…n+si-1。
    若opt=3,则是一组询问,后面输入一个字符串S,询问字符串S在当前trie中的出现次数。 
     

    Output

    对于每个opt=1或3,输出一行表示答案。
     

    Sample Input

    1
    4
    1 2 a
    1 3 b
    2 4 b
    6
    1
    2 2 4
    2 5 b
    2 6 c
    5 7 b
    1
    3 ab
    2 6 3
    6 8 a
    6 9 b
    1

    Sample Output

    3
    7
    2
    11
  • 相关阅读:
    MAC OSX 进程间通信
    UVa 10397 Connect the Campus
    ios 类似的效果淘宝商品详细页面
    Programming from the ground up(0)
    解决因特网和xshell考虑到问题
    除去在阵列中重复元件
    Cocos2d-x 手机游戏《疯狂的蝌蚪》资源 “开源” win32+安德鲁斯+iOS三合一
    (四)左右ng-app自己主动bootstrap相框
    Codeforces 338D GCD Table 中国剩余定理
    十月金在线编程竞赛的第二个冠军:解密
  • 原文地址:https://www.cnblogs.com/wang9897/p/9636859.html
Copyright © 2011-2022 走看看