总算是把这玩意搞懂并做了(
顺便把自己 SAM 构造算法的码风中的变量 whole 改成了 las(
考虑对于 T 中的每一个位置 i 求出 li=max{j∣Ti−j+1…i∈substrings(S)}
这意味着起点为 i−li+1 及其之后位置的 T1…i 的后缀都是 S 的子串。
首先考虑 l=1,r=|S| 怎么做。
这个要怎么求呢?容易发现 i−li+1 是不降的,证明的话考虑反证,那么可以推出 li 可以更大并与 max 矛盾。
设 len 表示当前的 li,p 表示 Ti−len+1…i 在 S 的后缀自动机上对应的状态。
那么如何从 i−1 转移到 li 呢?首先检查 p 是否有 Ti 的转移,如果有直接转移即可。
否则,一直令 len 自减,同时维护 p(即当 len 已经不属于 p 所包含的长度时将 p 跳至其父亲),直到 p 有 Ti 的转移。
(实际上,若 l=1,r=|S|,不需要自减,直接跳到父亲即可,因为自减在这一情况下并不会对转移造成任何改变。)
那么,对于一般情况(l≠1,r≠|S|),则我们要思考 Sl…r 的后缀自动机和 S 的后缀自动机有什么不同。
注意到 Parent Tree 是不会受影响的,所以只需要考虑如果检查 p 有 Ti 的转移。
若 p 在 S 上有 Ti 的转移,设转移到状态 q,那么便是需要知道 endpos(q)∩[l+len,r] 是否为空。
这个可以线段树合并解决。
但是求出这个之后,还需要去重。
考虑对 T 建后缀自动机,利用后缀自动机来去重。
对于状态 p,其贡献应为 max(0,len(p)−max(len(fa(p)),lr(p))),其中 r(p)=maxendpos(p)。
这个想必还是比较显然的,意即从这个状态包含的所有串中去掉 Sl…r 的子串。
代码:
1 |
|