后缀数组
特别注意: 下面的代码都是来自挑战程序设计竞赛, lcp[i]代表的是后缀Suffix[sa[i]]后缀Suffix[sa[i+1]]的最长公共前缀, 而网上比较流行的那个模板的height[i]则是后缀Suffix[i]与Suffix[sa[i-1]]的最长公共前缀, 挑战上的模板速度慢一些, 但是好写很多, 并且因为用的是快速排序数值范围比较大的时候不需要离散化
原理
为了方便处理一些情况, 我们把空串也当做一个后缀, 所以长度为n的字符串有n+1个后缀.
sa[i] 表示以S[sa[i]]开头的后缀是字符串所有后缀中字典序第i的.
rank[i]表示以S[i]开头的字符串在字符串所有后缀中排第rank[i]位.
用倍增法计算后缀数组.
记rk[i, j]为子串S[i…i+ 2j -1]在所有长度为 2j 长度的子串中的字典序排名, 如果i+ 2j -1超过了字符串的末尾, 则为S[i, n-1].
如果我们知道了所有的rk[i, j], 那么, 所有的rk[i, j+1]可以通过rk[i, j]和rk[i+ 2j , j]快速计算出来.
而一开始的rk[i, 0]是长度为1的子串, 可以直接通过每个字符的编码值得到(rk[i, 0] = int(S[i]);
).
代码
效率 O(nlo