1 条题解
-
0
题目理解
给定一棵 个节点的树,每个节点有一个大写字母。
再给一个长度为 的模式串 。
问有多少有序节点对 ,使得从 到 的简单路径上的字母连成的字符串,恰好等于 重复 次( 整数)。
样例分析
样例:
n=11, m=4 节点上的字母:IODSSDSOIOI 边: 1-2, 2-3, 3-4, 1-5, 5-6, 6-7, 3-8, 8-9, 6-10, 10-11 S = "SDOI"输出 5。
说明有 5 条路径的字符串是
SDOI重复整数次(这里主要是SDOI一次,因为 m=4,路径长度 4 的倍数才可能)。
思路分析
1. 路径特征
- 路径长度 (边数)必须是 的倍数,设 。
- 路径上第 个节点(从起点 开始数)的字符必须等于 。
2. 统计方法
- 最直接的想法是枚举所有 路径,不可行。
- 树上的路径统计问题,常用点分治。
- 在点分治框架下,考虑经过重心 的路径 ,将其拆成 (反向)和 (正向)两段。
- 我们需要合并两段路径,使得总长度 ,并且字符串匹配 的重复。
3. 字符串匹配处理
- 为了快速判断路径字符串是否匹配 ,使用字符串哈希。
- 预处理 重复两次的哈希值,方便计算任意 的哈希。
- 对于 的反向路径,需要反转后与 匹配,可以预处理 的反串的哈希。
4. 点分治中的匹配规则
设:
- = 的路径字符串(从 到 方向),长度为 。
- = 的路径字符串(从 到 方向),长度为 。
那么 的字符串是 ,总长度 。
条件:
- 必须匹配 的某个后缀, 必须匹配 的某个前缀,并且 正好是 的整数倍重复。
更具体:
- 设 。
- 那么 应等于 (即 的最后 个字符的反向?这里要注意方向),实际上 应当匹配 的前 个字符的反向?需要仔细推导。
实际上更稳妥的方法:
- 对 路径,记录哈希时按照从 到 方向计算哈希(即正向视为 的字符串),这样 反向就是正序 的字符串的反向,但哈希可以反向计算。
- 我们预先计算 的正向哈希 和反向哈希 。
- 在点分治时,对从重心 出发到 的路径,记录:
- 长度
- 哈希值 (从 到 方向)
- 反向哈希值 (从 到 方向,即路径反向的哈希)
合并时:
- 段用反向哈希(因为实际方向是 ,对应字符串是 的反向)
- 段用正向哈希
- 总哈希 = ,其中 是 的长度。
- 检查是否等于 ,其中 。
5. 优化
- 用哈希表存储从重心出发的路径信息(长度模 ,哈希值,方向等),然后匹配对应的“另一半”路径。
- 注意去重,保证 和 在重心的不同子树。
算法步骤
- 预处理 重复两次的正向哈希和反向哈希,以及 的幂。
- 点分治:
- 找重心
- 对每个子树 DFS,记录路径信息(长度,哈希,反向哈希,子树标号)
- 用哈希表统计当前已遍历子树的路径
- 遍历新子树时,先查询已存路径中能匹配的路径数,再加入新子树路径
- 统计所有经过重心的合法路径数。
- 递归处理子树。
复杂度
- 点分治
- 哈希比较
- 总复杂度 ,可过 数据。
- 1
信息
- ID
- 4384
- 时间
- 1500ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者