版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/85207671
传送门
题意简述:给出一棵
树,每个点表示一个字符,求树上所有路径组成的不同字串数。(叶子数
)
由于有一个神奇的条件,考虑以每一个叶子为树根统计每个点到树根的字串,这样就考虑到了所有情况,于是就这样建立广义
统计答案即可。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
const int N=4e6+5,M=1e5+5;
vector<int>e[M];
int n,c,a[M],du[M];
struct SAM{
int tot,last,len[N],link[N],son[N][10];
SAM(){tot=last=1,len[0]=-1;}
inline int expand(int p,int x){
if(son[p][x]){
int q=son[p][x],nq;
if(len[q]==len[p]+1)return last=q;
len[nq=++tot]=len[p]+1,memcpy(son[nq],son[q],sizeof(son[q])),link[nq]=link[q],link[q]=nq;
while(son[p][x]==q)son[p][x]=nq,p=link[p];
return last=nq;
}
int np=++tot;
len[np]=len[p]+1;
while(!son[p][x])son[p][x]=np,p=link[p];
if(!p)return link[np]=1,last=np;
int q=son[p][x],nq;
if(len[q]==len[p]+1)return link[np]=q,last=np;
len[nq=++tot]=len[p]+1,memcpy(son[nq],son[q],sizeof(son[q])),link[nq]=link[q],link[q]=link[np]=nq;
while(son[p][x]==q)son[p][x]=nq,p=link[p];
return last=np;
}
inline void query(){ll ret=0;for(ri i=2;i<=tot;++i)ret+=len[i]-len[link[i]];cout<<ret;}
}sam;
inline void dfs(int p,int fa,int x){
int tmp=sam.expand(x,a[p]);
for(ri i=0;i<e[p].size();++i)e[p][i]^fa?dfs(e[p][i],p,tmp):(void)0;
}
int main(){
freopen("lx.in","r",stdin);
n=read(),c=read();
for(ri i=1;i<=n;++i)a[i]=read();
for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u),++du[u],++du[v];
for(ri i=1;i<=n;++i)if(du[i]==1)dfs(i,0,1);
sam.query();
return 0;
}