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.两个字符串的最长公共子串
给定两个字符串 S 和 T ,求出最长公共子串。
直接把 T 扔到 S 的自动机上跑匹配就行了
- 9.求 endpos 集合
给定一个字符串 S,求 endpos 集合
首先我们能够求出每个节点的 pos
然后发现一个点的 endpos 就是他子树的 pos 的集合
怎么让一个点带上整个子树的某个值? 主席树合并啊!
每个点初始在主席树上插入 pos(i)
然后拓扑合并就行了
例题:你的名字
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络