专栏文章
DAG链剖分
算法·理论参与者 4已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @miozwcjw
- 此快照首次捕获于
- 2025/12/03 03:52 3 个月前
- 此快照最后确认于
- 2025/12/03 03:52 3 个月前
本文介绍的是针对于 SAM 上的 DAG 链剖分。
前置知识:SAM,树链剖分。
众所周知,我们可以快速在 SAM 上找到一个字符串,并且可以用一个节点在 parent 树上到根节点的路径表示一个字符串的所有后缀,但是无法很方便地表示一个字符串的所有前缀。
考虑一个字符串的所有前缀在 SAM 上对应的点是什么。
由于在一个字符串末尾添加字符相当于在 SAM 的 DAG 上走一条边,所以一个字符串的所有前缀对应了 DAG 上的一条路径。
考虑用类似树链剖分的思想,将 DAG 剖分成若干条重链,使得任意一条路径都可以拆分为 段重链。
设 表示在 DAG 上以 结尾的路径条数, 表示以 开头的路径条数。
设 表示 连向的点中 最大的那个, 表示连向 的点中 最大的那个,如果有最大值相同则任意取。
如果对于一条边 ,满足 且 ,则将这条边设置为重边,其余边设置为轻边。
则任意一条路径都能被剖分为 条重链。
证明:
首先,。
若 连向的点 满足 ,则 ,所以 。
同理,若连向 的 满足 ,则 。
设 表示 这个前缀在 DAG 上对应的点,显然 单调递增, 单调递减。
如果边 是轻边,则要么 至少乘 ,要么 至少除以 ,又因为 SAM 的 DAG 上总路径条数是关于 的多项式级别的,所以一条路径上不会有超过 条轻边。
具体实现可以直接通过二分哈希,实现 单次剖分。使用后缀数组求 lcp 可以做到 剖分。
有了这个做法后,我们可以做很多东西。
求区间最短 border、最长 border、border 个数。
考虑一个前缀是 border 的条件,也就是若 是 的后缀,则 是 的 border。
是 后缀相当于 在 SAM 的 parent 树上是 的祖先,所有 border 相当于 的所有在 SAM 上对应的点是 的祖先的前缀。
DAG 链剖分把 所有前缀剖分成 个区间,查询变成了一个点祖先中所有编号在一个区间内的点,直接主席树即可。
把模式串在 SAM 上标出来,问题转化为求一个区间所有子串的权值和。
预处理出来每个点的祖先的权值和,DAG 链剖分后转化为区间和,直接求前缀和即可。
但是这样可能会多算在同一个节点上的情况,多算的贡献是一个二维数点,总复杂度 。
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...