上周学习了后缀自动机。
于是蒟蒻
l
d
x
ldx
ldx在
D
Z
Y
O
DZYO
DZYO和
z
x
y
o
i
zxyoi
zxyoi的引导下逐渐对
s
a
m
sam
sam这个东西有了自己的认识。
c h a p t e r 1 chapter 1 chapter1 想法&总结
-
为啥会有 s a m sam sam这个东西?
因为 s a m sam sam可以做到利用 O ( n ) O(n) O(n)的时空来识别一个字串的 n 2 n^2 n2个字串。
因为 s a m sam sam的增量构造法可以支持在线操作。
因为 s a m sam sam建出的 p a r e n t parent parent树将所有状态的从属关系从图形转化成了树形。
因为 s a m sam sam建出的 p a r e n t parent parent树正是其反串的后缀树。
… -
自动机上的转移边
要谈转移边,就先要提到一个神奇的词语:状态。
还记得在学习搜索的时候,我们就已经开始接触状态这个词语了。
我对状态的理解就是:记录了某一类具有相同性质的事物的集合
而对于 s a m sam sam来说也同样是这样:同一个状态中的字串都有着相同的特点: e n d p o s endpos endpos集合相同。这些都是后话了
而两个状态之间的联系正是神奇的转移边。
也就是说,一个字串被识别的过程正对应着 D A G DAG DAG上的一条路径。
并且,这个关系是一个双射,即唯一的一个字串对应着一条唯一的路径妙不可言。 -
m a x l e n maxlen maxlen数组的妙用
在构建好 s a m sam sam之后,设一个状态的大小为 [ m i n l e n i , m a x l e n i ] [minlen_i,maxlen_i] [minleni,maxleni]。其后缀链接是 l i n k i link_i linki,那么有性质: m i n l e n i = m a x l e n l i n k i + 1 minlen_i=maxlen_{link_i}+1 minleni=maxlenlinki+1
还有就是两个状态的 l c p lcp lcp就是其 l c a lca lca的 m a x l e n maxlen maxlen大小。 -
s a m sam sam与回文串的判断
对原串建立一个后缀自动机,然后用反串在上面匹配。
如果当前匹配的区间 [ l , r ] [l,r] [l,r]包裹了当前状态的 e n d p o s endpos endpos中的最大值,那么 [ l , m a x p o s ] [l,maxpos] [l,maxpos]就是一个回文串。 -
广义 s a m sam sam
即对于所有的母串建立的后缀自动机。
广义 s a m sam sam的3种建法:
5.1. 每建完一个字串之后把 l a s t last last指向根节点
5.2. 一个一个建,如果当前已经有相同转移就看是否需要分裂
5.3. 离线 b f s bfs bfs按照层划分顺序来建。 -
s a m sam sam可以解决的问题(动态更新)
最长公共子串
第 k k k小的子串
第 k k k小的本质不同的子串
某一个字串在另一个字串里的出现次数
c h a p t e r 2 chapter 2 chapter2 题目收集
模板
求公共子串个数
求最长公共子串长度
求所有回文串出现次数
给两个字符串,让你求长度不小于k的公共子串的数量
给出最多10个串求最长公共子串
求第
k
k
k小子串
求长度为1~n的子串出现次数的最大值
支持动态在串尾插入字符,查询在串中出现超过k次的子串的个数
求
求
求后缀两两
l
c
p
lcp
lcp之和
给出n个字串,对每个串求出有多少个子串在至少k个字串中出现过
给出一棵trie树,求树上所有路径组成的不同字串数
给一个字串,对于每个位置求出经过这个位置且只在字串中出现一次的子串的长度的最小值