后缀数组 & 后缀自动机
本篇博文同时也作为 WC2021 Day2 的附文。
后缀数组
定义
后缀是什么?\(suffix_i = s_{i \cdots |s|}\)。
后缀数组包括 \(sa_i, rk_i\)。分别表示将 \(s\) 的所有后缀排序后,排名第 \(i\) 小的后缀的起始位置,和起始位置在 \(i\) 上的后缀的排名。
注:这里的“排名”指的是对这些后缀按照字典序排序后的排名。如果现在还不清楚什么是字典序,请自行搜索。
在阅读接下来的内容之前,请务必清楚理解 \(sa_i\) 和 \(rk_i\) 的含义,否则会导致接下来的内容理解困难。
为了协助大家理解这两个数组的含义,博主在这里举出一个例子。
这是一个字符串 \(S:\text{aabb}\)
为便于记录,我用一个二元组表示 \(S\) 的一个后缀极其起始位置,那么这个字符串的后缀所代表的二元组有:
\[\{\left(\text{aabb}, 1\right), \left(\text{abb}, 2\right), \left(\text{bb}, 3\right), \left(\text{b}, 4\right)\}
\]
将所有的后缀按照字典序排序,即:
\[\{\left(\text{aabb}, 1\right), \left(\text{abb}, 2\right), \left(\text{b}, 4\right), \left(\text{bb}, 3\right)\}
\]
回想之前的定义,\(sa_i\) 表示的是“排名为 \(i\) 的后缀的起始位置”。故 \(sa\) 数组为:\(\{1, 2, 4, 3\}\),\(rk_i\) 表示的是 “起始位置为 \(i\) 的后缀的排名”。故 \(rk\) 数组为 \(\{1, 2, 4, 3\}\)
emm 貌似这个例子举的不太好……
构造
倍增法构造 SA
直接找出所有后缀进行排序复杂度显然是 \(\mathcal O\left(n^2\right)\) 的,我们需要找到一种更快的方式构造后缀数组。
后缀自动机
构建 SAM
采用“增量法”,利用 \(S\) 的 SAM 构建出 \(S + c\) 的 SAM。
其中 \(S\) 是一个字符串,\(c\) 是一个字符,\(+\) 表示连接运算。

浙公网安备 33010602011771号