题目:

题目在这里

思路&做法:

参考的题解

既然只有\(20\)个叶子节点, 那么可以从每个叶子节点往上建一颗\(trie\)树, 然后合并成一棵大的\(trie\)树, 然后构建广义后缀自动机。

\((\) 实现起来就是dfs时把节点上的颜色加进广义后缀自动机\()\)

再然后就统计一下就可以了\((ans += len[x] - len[fail[x])\)

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cstring> using namespace std; const int N = 2000010; long long Ans; struct Suffix_Automaton
{ int nxt[N][10], fail[N], sz;
int len[N];
int root; Suffix_Automaton() { } inline int newnode(int l)
{ memset(nxt[sz], 0, sizeof(nxt[sz]));
fail[sz] = 0;
len[sz] = l;
return sz++;
} inline void init()
{ sz = 1;
root = newnode(0);
} int add(int c, int last)
{ if(nxt[last][c])
{ int p = last, q = nxt[p][c];
if(len[q] == len[p]+1)
return q;
else
{ int u = newnode(len[p] + 1);
for(int i=0; i<10; i++) nxt[u][i] = nxt[q][i];
fail[u] = fail[q];
fail[q] = u;
while(nxt[p][c] == q)
{ nxt[p][c] = u;
p = fail[p];
}
return u;
}
}
else
{ int now = newnode(len[last] + 1);
int p = last;
while(p && !nxt[p][c])
{ nxt[p][c] = now;
p = fail[p];
}
if(!p) fail[now] = root;
else
{ int q = nxt[p][c];
if(len[q] == len[p]+1)
fail[now] = q;
else
{ int u = newnode(len[p] + 1);
for(int i=0; i<10; i++) nxt[u][i] = nxt[q][i];
fail[u] = fail[q];
fail[q] = fail[now] = u;
while(nxt[p][c] == q)
{ nxt[p][c] = u;
p = fail[p];
}
}
}
Ans += (long long) (len[now] - len[fail[now]]);
return now;
}
}
} tzw; int color[N]; int r[N]; struct edge
{ int from, to;
edge() { }
edge(int _1, int _2):from(_1), to(_2) { }
} edges[2*N];
int head[N], nxt[2*N], tot; inline void init()
{ memset(head, -1, sizeof(head));
tot = 0;
} inline void Add_Edge(int x, int y)
{ edges[tot] = edge(x, y);
nxt[tot] = head[x];
head[x] = tot++;
edges[tot] = edge(y, x);
nxt[tot] = head[y];
head[y] = tot++;
} void dfs(int x, int fa, int last)
{ last = tzw.add(color[x], last);
for(int i=head[x]; ~i; i=nxt[i])
{ edge & e = edges[i];
if(e.to != fa)
dfs(e.to, x, last);
}
} int main()
{ int n, m;
scanf("%d %d", &n, &m);
for(int i=1; i<=n; i++)
scanf("%d", &color[i]);
tzw.init();
init();
for(int i=1; i<n; i++)
{ int x, y;
scanf("%d %d", &x, &y);
Add_Edge(x, y);
r[x]++, r[y]++;
}
for(int i=1; i<=n; i++)
if(r[i] == 1) dfs(i, 0, tzw.root);
printf("%lld\n", Ans);
return 0;
}

最新文章

  1. Silicon Labs
  2. MvcPager 免费开源分页控件3.0版发布!
  3. XE7 Update 1 选 iOS 8.1 SDK 发布 iPhone 3GS 实机测试
  4. 可以使用mysql自己带的config edit
  5. 循环不变量loop invariant 与 算法的正确性
  6. Eclipse中新建jsp文件访问页面时乱码问题
  7. Hadoop学习之--Capaycity Scheduler源码分析
  8. TWaver3D入门探索——3D拓扑图之绽放的小球花
  9. TNS-12541: TNS:no listener TNS-12560: TNS:protocol adapter error
  10. 所有做java开发的都是些垃圾
  11. Winform将一个窗体显示在另一个窗体中
  12. 数据库-SQL语句:删除和修改语句-列类型-列约束
  13. 【转】jquery.validate.js表单验证
  14. 记一次恐怖的 Integer 溢出
  15. JSTL标签用法:&lt;c:choose&gt;&lt;c:forEach&gt;&lt;c:if&gt;&lt;c:when&gt;&lt;c:set&gt;
  16. Websphere下删除某个文件(ibm-partialapp-delete.props)
  17. [原]openstack-kilo--issue(二) openstack auth error
  18. Linux系统下便捷使用中国知网的方式
  19. Python学习之路 (二)爬虫(一)
  20. mysql 源代码目录及安装目录介绍

热门文章

  1. 关于VirtualBox与锐捷冲突导致锐捷不断掉线的问题的解决办法
  2. WIN10 64位下VS2015 C#直接添加 halcon 12导出的CS文件实现视觉检测
  3. JavaScript的基本语法(一)
  4. python监听鼠标和键盘
  5. 实验8 标准模板库STL
  6. js开发性能(一)
  7. 进程映射、mmap(day05)
  8. BZOJ 4244 邮戳拉力赛 (DP)
  9. 百度之星2014资格赛 1003 - Xor Sum
  10. 洛谷——P1616 疯狂的采药