题意
给定一棵带边权 ${ 0, 1}$ 的无根树,求回文路径的个数。
其中 $3 \le n \le 5\times 10^4$。
分析
点分治,问题转化为求有多少条过当前重心的路径,使得其构成回文串。
将从重心开始的所有结点对应的串,插入 Trie 树中,最坏情况下 Trie 树与原树同构。
分析跨越重心 $root$ 路径的回文串结构,记两个端点分别为 $u,v$,其中 $u$ 的深度大于等于 $v$ 的深度。
深度相同,则 $root$ 到 $u$ 路径对应串 (简记为 $u$ 串) 必须等于 $root$ 到 $v$ 路径对应串 (简记为 $v$ 串)。令枚举的每个结点的出现次数为 $cnt$,这部分答案贡献为 $cnt \choose 2$。
深度不同,则 $v$ 串等于 $u$ 串的后缀,且 $u$ 串的前缀是一个回文串。
因此,我们考虑对 Trie 树构建 AC 自动机,则 $u$ 串的所有在 Trie 树中有对应结点的后缀就是 fail 树上的所有祖先。注意到,fail 树上的祖先可能很多,无法枚举并检查当前前缀是否为回文串。但是,根据 $Border$ 理论,一个串的回文后缀(前缀)可以表示为 $\log n$ 段等差数列。于是,我们处理所有 Trie 树结点的等差数列 $(l,r,d)$,对应表示首项、末项和公差。这可以在构建完 Trie 树后,dfs Trie 树,并维护正串和反串的哈希值得到。
最后,枚举所有 Trie 树结点,令其深度为 $len$,再枚举其等差数列,只需要询问 fail 树的祖先上长度为等差数列 $(len-r,len-l,d)$ 的出现次数和,进一步转化可以变成求所有长度 $l \equiv ((len-l) \bmod d) ( \bmod d)$ 的点值和,考虑根号分块容易维护,但是可能会取到一些等差数列值域外的点,可以将询问离线的最大长度上,并拆成两个前缀和,在 dfs fail 树的栈上二分即可获得对应结点。
总结
点分治。
插入从重心开始的 Trie 树。
dfs Trie 树,求出每个点回文前缀的等差数列。
dfs fail 树,维护栈上的结点,维护栈上支持快速查询模 $b$ 余 $r$ 处点值的分块数据结构。枚举等差数列,对于公差小的,栈上二分找到询问离线点,对于公差大的,暴力枚举。
枚举 Trie 树结点,计算回文前缀为空和不为空的匹配方案数。
点分治容斥掉来自同一子树的配对答案数。
时间复杂度:$T(n)=2T({n \over 2})+O(n \sqrt{n}+n\log^2 n)$,$T(n)=O(n \sqrt{n})$。