[ZJOI2015]诸神眷顾的幻想乡

Posted waing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZJOI2015]诸神眷顾的幻想乡相关的知识,希望对你有一定的参考价值。

[ZJOI2015]诸神眷顾的幻想乡

题意

树上每个点代表一个字符,问树上路径可以组成多少不同的字符串(叶子最多有20个)

题解

树上的路径一定是叶子为根的一条从上到下的路径,而叶子有很小,我们就可以把所有叶子构成的 trie 建成一个广义的 sam,最后统计不同字串个数即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=4000055; 
int tot,to[200005],co[100005],nextt[200005],head[100005],n,c,de[100005]; 
int cnt,last,l[N],ch[N][10],fa[N];
long long ans;
inline int read()
{
	int k=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c==‘-‘)f=-1;c=getchar();}
	while(isdigit(c)) k=k*10+c-‘0‘,c=getchar(); return f*k;
}
void add(int a,int b)
{
	to[++tot]=b;
	nextt[tot]=head[a];
	head[a]=tot;
}
int ins(int c,int p)
{
	if(ch[p][c])
	{
		int q=ch[p][c];
		if(l[p]+1==l[q]) last=q;
		else 
		{
			int nq=++cnt;l[nq]=l[p]+1;last=nq;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			fa[nq]=fa[q];fa[q]=nq;
			for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
		}
	}
	else 
	{
		int np=++cnt;last=np;l[np]=l[p]+1;
		for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
		if(!p) fa[np]=1;
		else 
		{
			int q=ch[p][c];
			if(l[p]+1==l[q]) fa[np]=q;
			else 
			{
				int nq=++cnt;l[nq]=l[p]+1;
				memcpy(ch[nq],ch[q],sizeof(ch[q]));
				fa[nq]=fa[q];fa[np]=fa[q]=nq;
				for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
			}
		 } 
	}
	return last;
 } 

void dfs(int u,int f,int p)
{
	int t=ins(co[u],p);
	for(int i=head[u];i;i=nextt[i])
	{
		if(to[i]!=f)
		{
			dfs(to[i],u,t);
		}
	}
}
int main()
{
	int a,b;
	n=read();c=read();cnt=last=1;
	for(int i=1;i<=n;i++) co[i]=read();
	for(int i=1;i<n;i++) a=read(),b=read(),add(a,b),add(b,a),de[a]++,de[b]++;
	for(int i=1;i<=n;i++)
	{
		if(de[i]==1)
		dfs(i,0,1);
	}
	for(int i=1;i<=cnt;i++) ans+=l[i]-l[fa[i]];
	printf("%lld
",ans);
	return 0;
}

以上是关于[ZJOI2015]诸神眷顾的幻想乡的主要内容,如果未能解决你的问题,请参考以下文章

[ZJOI2015]诸神眷顾的幻想乡

BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)

3926: [Zjoi2015]诸神眷顾的幻想乡

●BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

bzoj3926: [Zjoi2015]诸神眷顾的幻想乡

BZOJ3926[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机