CF917E Upside Down
大家好,我喜欢暴力数据结构,所以使用分块通过了此题。
给出
个点的树,第 条边上有字母 。有 个字符串 以及 组询问。每次询问给出 。 记
为 简单有向路径边上的字母按顺序拼接得到的字符串,形式化地,若 简单有向路径上一共有 条边,记 为 有向路径上的第 条边,则 。 求
在 中出现了多少次。形式化地,求有多少个正整数 使得 。 记
, 。
。
约定:
-
本文中所有下标均从
开始。钦定 为根。用打印机字体(\texttt
)表示具体的字符 / 字符串。 -
默认
, 。 -
记一个点
的父亲为 ,深度(到根的边数)为 。 -
表示 到 的简单有向路径, 这条边上的字符为 。特别地, 。 -
表示 两点的最近公共祖先。 表示两个字符串 的最长公共前缀。 -
记一个串
的反串为 。形式化地, 且 。 -
表示 向上走 条边到达的点,即 的树上 级祖先。 -
若字符参与运算,则其值等于其
值。
考虑弱化版 CF1045J 的做法,
在这部分中考虑使用哈希实现字符串匹配。我们的哈希方式为多项式哈希,即对于字符串
其中
在弱化版中,我们运用
在字符串总长度为
的长为 的字符串序列 中,本质不同的字符串长度种数为 级别。
考虑
种出现了 种本质不同的长度,从小到大依次是 ,记 表示第 种长度的出现次数,形式化地, 。 那么有:
。 可以发现
。后面那个很显然,因为这种长度出现时一定存在一个字符串满足其长度为 。 至于前面那个使用归纳法证明:
当
时 显然成立。 假设对于
时成立,则对于 时,由于 中的每一个数都是一种本质不同的长度,且从小到大排列,所以 。由于都是整数,所以 。 由于这里涉及到的量都是正的,所以
,因此 ,因此有 。可以得到 。注意这里不是在解不等式,由 推导出一个成立的条件。 证毕。
那么我们可以对于这
由于这个做法比较垃圾,我们不能在求解每种长度时重新遍历树计算哈希值,否则会超时。可以考虑牺牲空间,在第一次遍历树时就对于每个点存下这些哈希值。这样可以省去
具体地:
可以预处理
在求解每种长度时再考虑对于每种询问串的哈希值
至于询问,对于
此时,一共有
值得注意的是,为了将同种哈希值的询问一起做,考虑使用排序将它们排在一个连续的区间内时,需要使用基数排序确保排序复杂度线性,才能保证
考虑分别处理每种串
假设跨过直链的匹配发生在
同时,
考虑找到最长的长度
考虑一个基础问题:
给出字符串
,找到 的最长前缀使得它是 的后缀。求出这个最长长度。
解决方法是:找到
接下来证明正确性。
首先,这个
一定是同时是 的前缀和 的后缀。因为它是 的前缀又是它的 ,说明 存在这个 作为后缀。自然 也存在这个 作为后缀。记这里求出来的长度为 。 考虑是否存在更长的答案。假设存在更长的答案长度为
,其一定不超过 ,不然 就不是使得 长度更大的后缀了。此时, 与 存在长度为 的 。这时候 开头的 个字符形成的字符串与结尾的 个字符形成的字符串相等。此时 是 的一个更长的、长度不超过 的 ,矛盾。 因此不存在更长的答案,
即为所求。 证毕。
将原问题转化成上述形式,那么
因此,
先对
最长的长度不超过
因此,对于
接着考虑如何找到使得
接下来给出证明:
设它们的排名分别为
。则一定有 。因为根据定义,排名为 的后缀字典序大小已经超过了 ,但是排名在 内的后缀字典序大小都不超过 。 考虑反证,假设排名为
的后缀会得到更大的 长度。 记这个更大的
长度为 。分两种情况讨论:
若
,则排名为 的后缀的前 位均与 的前 位相同。根据 的定义可知其第 位也与 的这一位相同。根据定义,排名为 的后缀的第 位小于 的这一位,或者说这一位不存在(空字符)。此时,排名为 的两个后缀前 位相同都等于 的前 位。且后者的第 位大于前者的这一位。说明后者比前者字典序大,这与 矛盾。 若
,与上一种情况类似推导得到字典序大小上的矛盾即可证明。 证毕。
于是考虑求得排名
考虑如何求一条链上的字符串和序列上的字符串的最长公共前缀长度。对原树进行轻重链剖分,将边权转化为深度较深的端点的点权,则这条链会被表示成
一条一条重链匹配,若能全部匹配上,就算上这些长度,否则二分第一个不同的位置。只有第一条不匹配的重链需要二分,因此时间复杂度为
这部分细节比较多,尤其是一方匹配完的边界情况,具体看代码中的 qlcp
部分。
此时,这个过程已经求出了
那么
求出来之后,我们只需要考虑
记这
则
存在长度为 的 。 存在长度为 的 。 。
证明:
充分性:
因为
,所以跨过了 。因为 存在长度为 的 ,根据 的定义可以得到 ;因为 存在长度为 的 ,类似地, ,根据反串的定义得到 。两者拼接恰好是 。 必要性:
若
开头处可以形成合法的匹配,首先一定有 ,因为要跨过 。其次 ,根据 的定义, ,因此 ,即 存在长度为 的 ;类似地, ,因此 存在长度为 的 。 证毕。
所以,我们要统计有多少
转化成失配树上的限制,就是要求有多少
考虑离线 + 扫描线。对于所有
在 的当前搜到的点 的根链上。 在 中点 的根链上。 。
则只要在
每次新扫到一个点
这部分就做完了,时间复杂度为
综上,这个做法时空复杂度均为
码量 12.5 KB。
总结一下,本题考察了一下几方面的知识:
- 思想:离线、扫描线、平衡复杂度等。
- 树论:轻重链剖分、最近公共祖先等。
- 数据结构:树状数组、分块等。
- 字符串:后缀数组、失配树、字符串哈希等。
- 数论:快速幂、乘法逆元等。
题目思路巧妙、性质极多、码量极大,对于选手的思维能力和代码能力都是一种不小的挑战,算是一道不可多得的字符串神仙 & 毒瘤题目。
完结撒花!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!