给一颗n(1 ≤ n ≤ 300 000)个节点的树,root=1,每个节点上有一个字母,每个子树从根开始向下遍历到任意节点停下,经过的不同字符串个数为diff[i],
已知
ci
,求
max(diffi+ci)与符合条件的i的个数
求出
diffi
就行
考虑给每个子树建一颗字典树,然后不断合并字典树
然后优先让节点数大的向小的合并
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=300005;
const int SIGMA_SIZE=26;
int sz=0;
struct Node
{
int sz, ch[SIGMA_SIZE];
}nd[maxn<<1];
int newnode()
{
++sz;
memset(nd[sz].ch, 0, sizeof(nd[sz].ch));
return sz;
}
int N;
LL C[maxn];
char s[maxn];
vector<int> G[maxn];
void init()
{
scanf("%d", &N);
for(int i=1; i<=N; i++)
{
G[i].clear();
scanf("%I64d", &C[i]);
}
scanf("%s", s+1);
int u, v;
for(int i=1; i<N; i++)
{
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
}
void maintain(int u)
{
nd[u].sz=1;
for(int i=0; i<SIGMA_SIZE; i++)
if(nd[u].ch[i])
nd[u].sz+=nd[nd[u].ch[i]].sz;
}
void Merge(int &a, int b)
{
if(a==0) a=b;
else
{
for(int i=0; i<SIGMA_SIZE; i++)
{
if(nd[b].ch[i])
Merge(nd[a].ch[i], nd[b].ch[i]);
}
}
maintain(a);
}
int dfs(int u, int f)
{
int p=newnode();
for(int i=0; i<G[u].size(); i++)
{
int v=G[u][i];
if(v==f) continue;
Merge(p, dfs(v, u));
}
maintain(p);
int r=newnode();
nd[r].ch[s[u]-'a']=p;
maintain(r);
C[u]+=nd[r].sz-1;
return r;
}
int main()
{
init();
dfs(1, 0);
LL ans=0, cnt=0;
for(int i=1; i<=N; i++)
{
if(C[i]>ans) ans=C[i], cnt=0;
if(C[i]==ans) cnt++;
}
printf("%I64d\n%I64d\n", ans, cnt);
return 0;
}