首先考虑如何用 SAM 求多串 LCP。
考虑选取一个基准串,对其他串建 SAM 并把基准串分别放到上面匹配,同位置的匹配长度的最小值的最大值即为答案。
当然,对基准串建 SAM 并把别的串匹配并打标记也是可以的。
若基准串为 sx,则复杂度为 O(|sx|n+∑|si|)。
对于此题,考虑用类似猫树的方式进行分治并计算答案。
出题人给出了一种十分玄妙的分治方法:倍增处理。
设一个阈值 lim,分治时将区间内长度不超过 2lim 的串拿出来,取中点作为基准串。
若一个区间内不存在长度不超过 2lim 的字符串,令 lim 加一。
则分治部分的复杂度为 O(nlog2n)(视 n,∑|si| 同阶)。
统计答案的部分复杂度看起来不大对。
但是有结论:若将询问记忆化,复杂度为 O(n√m)。
证明:
首先容易发现对于当前分治区间,2lim 是 O(1n∑|si|) 级别的(考虑 2lim 与最短串长度的关系)。
分类讨论。
若某个区间的最短串长度不超过 m−1/2∑|si|,复杂度共为 O(n√m)。
若某个区间的最短串长度超过 m−1/2∑|si|,这个区间对应的询问最多有 O(m) 种,复杂度同样为 O(n√m)。
(视 n,∑|si| 同阶)
总复杂度大概是 O(n(log2n+√m))。
(我不知道为什么要开 O2 才能过 /kel)
代码:
1 |
|