BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串

时间:2022-05-05 15:13:48

https://www.lydsy.com/JudgeOnline/problem.php?id=3926

广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比较方便)。

后缀自动机可以说是一种存子串的缩小点数的trie树,广义后缀自动机就是更改了一下塞点的方式让它可以塞多个串的子串。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define LL long long
const int maxn=;
int n,c;
int val[maxn]={};
struct nod{
int y,next;
}e[maxn*];int head[maxn]={},tot=;
int a[maxn]={};
struct node{
int sig[],f,len;
}t[maxn*];int tly=;
inline void init(int x,int y){ e[++tot].y=y; e[tot].next=head[x]; head[x]=tot; }
int addit(int k,int z){
int x=++tly; t[x].len=t[k].len+;
for(;k&&!t[k].sig[z];k=t[k].f)
t[k].sig[z]=x;
if(k==)t[x].f=;
else{
int y=t[k].sig[z];
if(t[y].len==t[k].len+)t[x].f=y;
else{
int p=++tly; t[p]=t[y]; t[p].len=t[k].len+;
t[x].f=t[y].f=p;
for(;k&&t[k].sig[z]==y;k=t[k].f)
t[k].sig[z]=p;
}
}
return x;
}
void dfs(int x,int fa,int k){
int nt=addit(k,val[x]);
for(int i=head[x];i;i=e[i].next)
if(fa!=e[i].y)dfs(e[i].y,x,nt);
}
int main(){
memset(t,,sizeof(t));
int x,y;
scanf("%d%d",&n,&c);
for(int i=;i<=n;++i)scanf("%d",&val[i]);
for(int i=;i<n;++i){
scanf("%d%d",&x,&y);
init(x,y);init(y,x); a[x]++;a[y]++;
}
for(int i=;i<=n;++i)if(a[i]==)dfs(i,,);
LL ans=;
for(int i=;i<=tly;++i)ans+=(LL)(t[i].len-t[t[i].f].len);
printf("%lld\n",ans);
return ;
}