后缀数组

  1. 基数排序
    算法思想:利用桶的单调性,从低到高位依次将整数放进对应数位的桶中。
    时间复杂度:\(O(d*(n+siz))\),其中 \(d\) 为数位,\(n\) 为元素个数,\(siz\) 为桶的大小。

  2. 后缀树
    对于字符串 \(s\),取出 \(s\) 所有的后缀字串,并建立字典树。这个树就是 \(s\) 的后缀树。空间复杂度 \(O(N^2)\)

  3. 后缀数组 SA
    对于字符串 \(s\),定义 sa[i] 表示 \(s\)\(n\) 个后缀按字典序排序后的第 \(i\) 个后缀在 \(s\) 中的下标,其中 \(i\)\(0\) 开始。

  4. 后缀数组的实现
    直接使用 sort 排序,由于字符串的比较是 \(O(n)\) 的,总时间复杂度 \(O(n^2\times \log n)\)

倍增求 sa[]

  1. \(s\) 中的字母按照字典序从 \(1\) 开始分配整数。
  2. 倍增拼接连续 \(1,2,4,...,\log n\) 的整数来代表每个后缀的排名,当拼接的数字互不相同时即停止,由得到的数字 sort 即可确定字典序。
    最坏复杂度 \(O(n\log^2 n)\)
    拼数的时候可以每次重新编号,长度控制在两位数。
  3. 利用基数排序的优化
    拿基数排序替换快排。d=2,所以跑的很快。

rnk[i] 表示以下标 \(i\) 开头的后缀在排序后的排名。

易知 sa[rnk[i]]=i;rnk[sa[i]]=i;

height[i] 表示 lcp(sa[i-1],sa[i])

应用:

  • 在串里找最长重复子串:max(height)
  • 找s和t的最长公共子串:在s+"#"+t里做最长重复子串,且sa[i-1]和sa[i]在两边。
  • 本质不同子串数量:\(n\times (n+1)/2-\sum height\)
posted @ 2023-10-01 21:02  Forever1507  阅读(10)  评论(0编辑  收藏  举报