Description
幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日。
Input
第一行两个正整数n,c。表示空地数量和颜色数量。
Output
一行,输出一个整数,表示答案。
Sample Input
0 2 1 2 1 0 0
1 2
3 4
3 5
4 6
5 7
2 5
Sample Output
HINT
对于所有数据,1<=n<=100000, 1<=c<=10。
Solution
广义$SAM$,也就是给一个$Trie$建$SAM$。具体操作很简单,就是$DFS$一下$Trie$树,每次将一个字符插入$SAM$的时候,将$SAM$的$last$记为这个字符在$Trie$树上的父亲的$np$就可以了。
由于一种字符串只能做出一次贡献,所以答案为$ans=\sum step[i]-step[fa[i]]$
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N (2000009) 5 #define M (100009) 6 #define LL long long 7 using namespace std; 8 9 struct Edge{int to,next;}edge[M<<1]; 10 int head[M],num_edge; 11 int n,m,u,v,a[M],Ind[M]; 12 13 void add(int u,int v) 14 { 15 edge[++num_edge].to=v; 16 edge[num_edge].next=head[u]; 17 head[u]=num_edge; 18 } 19 20 struct SAM 21 { 22 int son[N][12],fa[N],step[N],wt[N],od[N]; 23 int p,q,np,nq,cnt; 24 SAM(){cnt=1;} 25 26 int Insert(int last,int x) 27 { 28 p=last; np=++cnt; step[np]=step[p]+1; 29 while (!son[p][x] && p) son[p][x]=np, p=fa[p]; 30 if (!p) fa[np]=1; 31 else 32 { 33 q=son[p][x]; 34 if (step[p]+1==step[q]) fa[np]=q; 35 else 36 { 37 nq=++cnt; step[nq]=step[p]+1; 38 memcpy(son[nq],son[q],sizeof(son[q])); 39 fa[nq]=fa[q]; fa[q]=fa[np]=nq; 40 while (son[p][x]==q) son[p][x]=nq, p=fa[p]; 41 } 42 } 43 return np; 44 } 45 void Calc() 46 { 47 LL ans=0; 48 for (int i=1; i<=cnt; ++i) 49 ans+=(LL)(step[i]-step[fa[i]]); 50 printf("%lld\n",ans); 51 } 52 }SAM; 53 54 void DFS(int x,int fa,int pre) 55 { 56 int tmp=SAM.Insert(pre,a[x]); 57 for (int i=head[x]; i; i=edge[i].next) 58 if (edge[i].to!=fa) DFS(edge[i].to,x,tmp); 59 } 60 61 int main() 62 { 63 scanf("%d%d",&n,&m); 64 for (int i=1; i<=n; ++i) 65 scanf("%d",&a[i]); 66 for (int i=1; i<=n-1; ++i) 67 { 68 scanf("%d%d",&u,&v); 69 add(u,v); add(v,u); 70 Ind[u]++; Ind[v]++; 71 } 72 for (int i=1; i<=n; ++i) 73 if (Ind[i]==1) DFS(i,-1,1); 74 SAM.Calc(); 75 }