请问我是怎么忘记在构造 SAM 复制结点的时候忘记清空别的东西,还把倍增循环顺序打反的……
这道题告诉我,请不要怀疑你的广义 SAM 模板(本来以为是这个出锅了
首先对 \(T_{1\dots m}\) 建广义后缀自动机,然后对 \(S\) 中的每个位置 \(i\) 求出 \(S_{1\dots i}\) 最长的为 \(T_{1\dots m}\) 中子串的后缀,这个是后缀自动机基本操作。
即,记录当前后缀在后缀自动机上对应的状态,当新增字符时查看是否有对应转移,如果有直接转移并更新长度,如果没有则跳 Parent Tree 直到有转移。
记这个后缀的长度为 \(l_i\),并同时记录这个后缀在后缀自动机上对应的状态 \({\rm ed}_i\)。
询问时,考虑 \({\rm ed}_{p_r}\),倍增在其祖先(即后缀)中找到一个最浅(即 \(\rm len\) 最小)的状态 \(u\),则包含 \(S_{p_l\dots p_r}\) 的状态恰为 \(u\) 子树内所有状态。
那么如何求答案?考虑以 \(1\dots m\) 为下标在后缀自动机上维护线段树,表示这个状态在 \(T_{1\dots m}\) 中某个串中的出现次数,然后维护众数,线段树合并即可。
(广义后缀自动机套雨天的尾巴(雾
然而注意特判几个不存在的情况。
代码:
1 |
|