SA

复习。

这玩意主要用来求 LCP,最长公共前缀。但是在一些时候可以写二分哈希代替 SA。

对一个字符串进行后缀排序,即把后缀按字典序排序。

考虑倍增。我们排序后缀的前 \(2^i\) 位,然后排序 \(2^{i+1}\) 位时,只需把后缀 \(j\) 的前 \(2^i\) 位的排名和后缀 \(j+2^i\) 的前 \(2^i\) 位的排名当作第一二关键字拿出来做排序即可。

直接 sort 是 \(O(n \log^2 n)\) 的,但是可以桶排。这样复杂度就是 \(O(n \log n)\)

具体来说,你把每个后缀的第一二关键字搞好,然后先按第二关键字进行一次桶排,再按第一关键字桶排,就可以两个关键字都排好序了。桶排的流程,无脑的做法可以把值对应的计数器累加,然后求前缀和,取出的时候只需看对应位置计数器的前缀和即可。

最后排好序之后求一下新的值域(就是已经确定不同的后缀数量)即可。如果值域已经是 \(n\) 了就可以结束了。

求 LCP:

引理是 \(LCP(i,j)=\min_{i<k\le j} LCP(k-1,k)\)

其中 \(LCP(i,j)\) 指后缀排序中排名 \(i,j\) 的两个后缀的最长公共前缀。

然后还有引理是 \(LCP(j,j+1)\ge LCP(j-1,j)-1\)

于是预处理,然后 ST 表 \(O(1)\) 查询即可。

posted @ 2023-03-23 19:09  infinities  阅读(280)  评论(0编辑  收藏  举报