码迷,mamicode.com
首页 > 其他好文 > 详细

luogu3346 诸神眷顾的幻想乡 (广义SAM)

时间:2019-01-01 18:52:58      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:roo   幻想乡   amp   include   fread   read   long   names   tin   

首先,让每一个叶节点做一次树根的话,每个路径一定至少有一次会变成直上直下的

于是对于每个叶节点作为根产生的20个trie树,把它们建到同一个广义SAM里

建法是对每个trie dfs去建,last就是父亲的那个节点;每次做一个新trie时,last给成root

然后答案就是每个节点表示的长度和

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 #define MP make_pair
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn=1e5+10,maxp=4e6+10;
 8 
 9 inline char gc(){
10     return getchar();
11     static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf;
12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
13 }
14 inline ll rd(){
15     ll x=0;char c=gc();bool neg=0;
16     while(c<0||c>9){if(c==-) neg=1;c=gc();}
17     while(c>=0&&c<=9) x=(x<<1)+(x<<3)+c-0,c=gc();
18     return neg?(~x+1):x;
19 }
20 
21 int N,C,eg[maxn*2][2],egh[maxn],ect,dgr[maxn];
22 int col[maxn];
23 int tr[maxp][12],fa[maxp],len[maxp],pct=1,rt=1;
24 
25 inline void adeg(int a,int b){
26     eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect;
27     dgr[a]++;
28 }
29 
30 inline int insert(int x,int o){
31     int p=++pct;
32     len[p]=len[o]+1;
33     for(;o&&!tr[o][x];o=fa[o]) tr[o][x]=p;
34     if(!o){fa[p]=rt;return p;}
35     int q=tr[o][x];
36     if(len[q]==len[o]+1){fa[p]=q;return p;}
37     int qq=++pct;
38     memcpy(tr[qq],tr[q],sizeof(tr[qq]));
39     len[qq]=len[o]+1;fa[qq]=fa[q],fa[q]=fa[p]=qq;
40     for(;o&&tr[o][x]==q;o=fa[o]) tr[o][x]=qq;
41     return p;
42 }
43 
44 inline void dfs(int x,int f,int p){
45     p=insert(col[x],p);
46     for(int i=egh[x];i;i=eg[i][1]){
47         int b=eg[i][0];if(b==f) continue;
48         dfs(b,x,p);    
49     }
50 }
51 
52 int main(){
53     //freopen("","r",stdin);
54     int i,j,k;
55     N=rd(),C=rd();
56     for(i=1;i<=N;i++) col[i]=rd();
57     for(i=1;i<N;i++){
58         int a=rd(),b=rd();
59         adeg(a,b);adeg(b,a);
60     }
61       for(i=1;i<=N;i++){
62           if(dgr[i]==1) dfs(i,0,rt);
63       }
64       ll ans=0;
65       for(i=2;i<=pct;i++) ans+=len[i]-len[fa[i]];
66     printf("%lld\n",ans);
67     return 0;
68 }

 

luogu3346 诸神眷顾的幻想乡 (广义SAM)

标签:roo   幻想乡   amp   include   fread   read   long   names   tin   

原文地址:https://www.cnblogs.com/Ressed/p/10205462.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!