字符串杂记

发布时间 2024-01-02 20:57:34作者: jeefy

Cage 字符串听课笔记

关于 border

神秘的性质……他们是怎么想到的?

P5287 给到的技术是 KMP 自动机,利用可持久化线段树做到 \(O(n \log |\Sigma|)\) 的复杂度不均贪的完成 KMP 的匹配过程。考虑 KMP 的过程,实际上是跳 fail 树上第一个具有 c 出边的点,观察到每次只会修改一个点,可持久化就简单了。对于本题来说正是利用这个过程,只是稍微抽象了一点,因为一次加了多个相同的字符,那么可持久化就需要一个 tuple。转移的时候增加的是一个等差数列,继承答案转移即可。

然而对于 JOJO 这道题来说,还有一种与 border 性质更相关的做法。注意到 period 可以被划分为 \(O(\log n)\) 个等差数列,实际上 fail 树也可以被划分为若干的等差数列,并且,\(x\) 到根的链上也只有 \(O(\log n)\) 次变换,那么如果据此链剖分,那么就可以做到 \(O(n \log n)\) 的复杂度,与 \(|\Sigma|\) 没有关系了。然而我实际是不会写的。

关于 SAM

  • 在 SAM 上 \(lcp(i, j)\) 就是 \(i, j\) 对应点在 parent 树上 \(\mathrm{lca}\)\(\mathrm{len}\)P4248
  • 可以利用倍增找到某个子串的出现次数。P3649
  • 串的匹配,放在 SAM 节点上转移即可,如果没有就跳 link,注意更新长度 P6640。本题中还需要狠狠注意匹配的单调性,设 \(len_i\) 表示从 \(i\) 开始最长的公共串长,虽然 \(len_i\) 不满足单调性,但是 \(i + len_i\) 是满足的,考虑不可能存在包含的情况。于是就是一个简单的二分和 RMQ 问题。
  • 出现与非出现的问题,CF427D,考虑出现一次的串,那么在 SAM 上的体现就是为叶子,对应的长度就是只出现一次的长度。两个串都要满足的话就需要建立两个 SAM,一个作为模板,一个提前记录位置即可。
  • 两个自动机内的问题 P4608 善用记忆化即可。

关于 SEQAM

参考:# 算法学习笔记(90): 序列自动机

仍然注意可以利用可持久化线段树完成 \(O(n \log n)\) 构建。

1295C - Obtain The String 超简单。

关于广义 SAM

两种写法。

  • 离线将所有串建出 Trie,然后在其上 bfs,正常的插入 SAM 即可。
  • 在线,还是正常的 SAM,但是特判,参考 题解 的代码。大概就是将有 ch[p][c] 的情况特判出来,其他都是一样的。

关于字典序的比较

最简单也最万能的就是二分哈希找第一个不同,直接判断即可。

序列最小表示法也可以用这个方法比较做到 \(O(n \log n)\)