Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

SAM(后缀自动机)专题总结

这是一篇其实理解并不深刻只会打板子的蒟蒻写出的总结

分成几个板块吧。。。。。。

  • 1.检查字符串是否出现

  给一个文本串 T 和多个模式串 P,我们要检查字符串 P 是否作为 T 的一个子串出现。

\ 对 T 建出 SAM

\ 直接在后缀树上从根开始往下走,如果能走到 P 结尾说明是模板串的子串

  • 2.不同子串个数

  给一个字符串 S,计算不同子串的个数。

\ 静态:我们知道每个子串就是后缀DAG上的一条路径

\ \ \ \ \ \ DAG上路径数怎么统计就不用说了吧

\ 动态:每次新建一个节点,贡献为len(np)len(f(np))

\ \ \ \ \ \ 好像挺显然的?

  例题:生成魔咒

  • 3.最小循环移位

给定一个字符串 S 。找出字典序最小的循环移位

发现字符串 S+S 包含字符串 S 的所有循环移位作为子串。

所以问题变为在 S+S 对应的后缀自动机上寻找最小的长度为 |S| 的路径

直接从初始状态开始,贪心地访问最小的字符即可。

  例题:工艺

  • 4.出现次数

对于一个给定的文本串 T ,有多组询问,每组询问给一个模式串 P ,回答模式串 P 在字符串 T 中作为子串出现了多少次

我们发现用如果模式串在 SAM 上跑匹配,那么最终到达的点的 endpos 就是该串的出现次数

考虑 endpos 的处理根据定义发现其实就是后缀树上的子树大小

所以我们把实点权值设为 1,虚点设为 0,跑拓扑就行了

 例题:substring(需要动态维护 endpos,打棵 lct 呗)

  • 5.字典序第 k 大子串

给定一个字符串 S 。多组询问,每组询问给定一个数 K​ ,查询 S 的所有子串中字典序第 K​ 大的子串。

字典序第 K 大的子串对应于 SAM 中字典序第 k 大的路径

那么在计算每个状态的路径数后,就可以从 SAM 的根开始找到第 k 大的路径。

 例题:弦论

  • 6.第一次出现的位置

给定一个文本串 T ,多组查询。每次查询字符串 P 在字符串 T 中第一次出现的位置( P 的开头位置)。

预处理出每个状态第一次出现的位置pos(i)

其实只需要让每次pos(np)=len(np) pos(nq)=pos(q)就好了

查询答案为pos(i)|T|+1

  • 7.最短的没有出现的字符串

给定一个字符串 S 和一个特定的字符集 T,我们要找一个长度最短的没有在 S 中出现过的字符串

SAM 上做 dp

dpi 表示到点 i 时的最短长度

如果这个点有不是 T 中字符的出边,则 dpi=1,否则 dpi=1+min

  • 8.两个字符串的最长公共子串

给定两个字符串 ST ,求出最长公共子串。

直接把 T 扔到 S 的自动机上跑匹配就行了

  • 9.求 endpos 集合

给定一个字符串 S,求 endpos 集合

首先我们能够求出每个节点的 pos

然后发现一个点的 endpos 就是他子树的 pos 的集合

怎么让一个点带上整个子树的某个值? 主席树合并啊!

每个点初始在主席树上插入 pos(i)

然后拓扑合并就行了

  例题:你的名字

posted @   mikufun♘  阅读(805)  评论(0编辑  收藏  举报
编辑推荐:
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络
点击右上角即可分享
微信分享提示