幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日。
幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日。
第一行两个正整数n,c。表示空地数量和颜色数量。
一行,输出一个整数,表示答案。
对于所有数据,1<=n<=100000, 1<=c<=10。
解题思路:广义后缀自动机,由于叶子节点比较少,对于每个叶子节点,dfs
将每个状态放入后缀自动机。然后最后在自动机上统计答案。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,c,len,cnt;
long long ans;
int to[200001],next[200001],h[200001];
int mx[4000005],fa[4000005],ch[4000005][10];
int a[100005],line[100005];
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0'&&y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void ins(int x,int y)
{
++len; to[len]=y; next[len]=h[x]; h[x]=len;
}
int insert(int now,int lp)
{
int p=lp; int np=++cnt; mx[np]=mx[p]+1; int zhi=cnt;
while (p && !ch[p][a[now]]) ch[p][a[now]]=np,p=fa[p];
if (!p)fa[np]=1;else
{
int q=ch[p][a[now]];
if (mx[q]==mx[p]+1)
{
fa[np]=q;
}else
{
int nq=++cnt; mx[nq]=mx[p]+1;
fa[nq]=fa[q];
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[np]=fa[q]=nq;
while (ch[p][a[now]]==q) ch[p][a[now]]=nq,p=fa[p];
}
}
return zhi;
}
void dfs(int now,int fa,int po)
{
int uq=insert(now,po);
int u=h[now];
while (u!=0)
{
if (to[u]!=fa)
{
dfs(to[u],now,uq);
}
u=next[u];
}
}
int main()
{
n=read(); c=read();
for (int i=1;i<=n;++i)
a[i]=read();
for (int i=1;i<=n-1;++i)
{
int x=read(); int y=read();
ins(x,y);ins(y,x);
++line[x]; ++line[y];
}
cnt=1;
for (int i=1;i<=n;++i)
if (line[i]==1)
{
dfs(i,0,1);
}
ans=0;
for(int i=1;i<=cnt;i++)
ans+=mx[i]-mx[fa[i]];
printf("%lld",ans);
}