SAM
后缀自动机(SAM)
节点意义:记录一组\(r\)相同的长度连续的子串\(s[l:r]\),\(len(x)\)表示最长的一个
\(son\)指针意义:在x记录的每一个子串后面都加上\(c\)后可以得到son(x,c)中的一个连续段(本质上是一个映射关系)
son指针仅仅是单向映射关系,因此可能会有多个y指向同一个x,比如x={cd,bcd,abcd},y1={c},y2={bc,abc},那么son(y1,d)和son(y2,d)都指向x,其中y1对应着{cd},而y2对应着{bcd,abcd}
\(fa\)指针意义:\(fa(x)\)记录的子串均是\(x\)记录的子串的后缀且是\(len\)最大的一个
构建:
-
以\(prv\)为基础
- 若\(prv\)没有这个儿子,
son(prv)=x,prv=fa(prv)
- 若\(prv\)没有这个儿子,
-
若\(prv\)跳到根了,则令\(fa\)=根
-
否则令\(p\)为\(son(prv,c)\)
- 若\(len(p)=len(prv)+1\),
fa(x)=p
- 否则新建一个\(newp\)为\(p\)的复制(fa和son信息相同),并将连向\(p\)的节点改成连向newp,并令\(len(newp)=len(prv)+1\),然后
fa(x)=fa(p)=newp
- 若\(len(p)=len(prv)+1\),
构建过程中唯一难理解的问题在于为什么要复制一个p,主要原因是\(son\)指针的单向对应关系
举个例子,prv={ab,aab},p={abc,aabc,eaabc,eeaabc},x={abc,aabc,daabc},直接连fa不好处理
这个时候prv对应到p中为{abc,aabc},对应到x中为{abc,aabc},发现这两个集合是一样的,所以直接提出来(即newp),得到4个集合
prv={ab,aab},newp={abc,aabc},p={eaabc,eeaabc},x={daabc}
然后son和fa指针就可以很方便地处理了
应用扩展
广义SAM:多个字符串的SAM,有离线(trie+bfs)和在线两种做法(蒟蒻知道的最好写的在线做法就是每次插入一个新的串时把prv改成1,然后加点特判避免空节点)
利用parent树将匹配/公共串一类的字符串问题转化成更直观的树上问题
利用lct的Access操作和爬parent树的相似性,去维护到根链的相关信息(区间本质不同子串个数)