[学习笔记] SAM及其应用
这几天学 SAM 学懵了。写篇学习笔记整理整理。
注意,本篇博客不是 SAM 入门教程。如果想要入门,建议看OI-wiki或者一篇不错的blog
接下来叙述 SAM 的几个例题。
SP48 BEADS - Glass Beads
非常基础的一个题。
我们的SAM有一个非常重要的性质,就是说从起点开始,沿着转移走,可以走遍所有的子串,而且其中没有重复。
那么这个题的做法就非常显然。我们复制一遍原字符串,贪心地每次选取最小的转移跑
为什么每次选取最小的一定可以跑至少
因为我们的 SAM 串是由一个字符串复制一遍而来的。跑到的第一个状态的实际位置不会在后半段出现。
做完了。顺便有个双倍经验题P1368.
SP8222 NSUBSTR - Substrings
非常板子的一个题。题意就是统计每个长度的字符串的出现次数的最大值。
我们发现一个节点的
然后我们有一个性质,对于一个节点
为什么要加是否是一个前缀呢?
我们考虑这个前缀的endpos是不可能由
至于为什么这样就可以考虑全的话可以类似地反证。
最后瞎上一个数据结构,每次枚举所有状态,把
SP7258 SUBLEX
非常板子的一个题。
我们首先考虑怎么求出一个点
到了一个状态以后有两种情况
-
不走了,则出现一个子串
-
往下走,则
siz_u 增加siz_v
dp 一遍就好了,注意一下根节点的特判
最后类似主席树求第
SP1811 LCS - Longest Common Substring
不会用后缀数组,太难了。
不会广义后缀自动机,连篇讲稿都找不到。
我们考虑裸 SAM 解决。
我们对于第一个字符串
我们考虑求一个字符串的所有子串的经典化法是求该字符串的所有前缀的后缀。
直接在 SAM 上把第二个字符串
如果一直没有就重新开始。最后对所有搞定了。
SP1812 LCS - Longest Common Substring2
不会广义后缀自动机,连篇讲稿都找不到。
我们还是对于第一个字符串
显然这次不可以基于每一个其他字符串搞了。我们就要在这个 SAM 上边做做文章。
考虑搞出每一个节点可以匹配到的最大值。
我们考虑对于一个前缀的所有后缀,有可能和它匹配的点一定在parent树上最优匹配点->根节点上。别的点不可能和这些后缀匹配。
然后我们发现这一串点并不能在过来的途中被经过,所以需要更新一遍。
最后因为是很多个串搞,所以要取个min。