两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
2020-2021:teams:legal_string:后缀数组_lgwza [2020/07/24 16:10] lgwza |
2020-2021:teams:legal_string:后缀数组_lgwza [2020/07/24 16:17] (当前版本) lgwza [一些常数优化] |
||
---|---|---|---|
行 43: | 行 43: | ||
参考代码: | 参考代码: | ||
+ | <hidden> | ||
<code cpp> | <code cpp> | ||
#include <algorithm> | #include <algorithm> | ||
行 86: | 行 87: | ||
} | } | ||
</code> | </code> | ||
+ | </hidden> | ||
==== $O(n\log n)$ 做法 ==== | ==== $O(n\log n)$ 做法 ==== | ||
行 97: | 行 98: | ||
参考代码: | 参考代码: | ||
+ | <hidden> | ||
<code cpp> | <code cpp> | ||
#include <algorithm> | #include <algorithm> | ||
行 147: | 行 149: | ||
} | } | ||
</code> | </code> | ||
+ | </hidden> | ||
==== 一些常数优化 ==== | ==== 一些常数优化 ==== | ||
行 158: | 行 161: | ||
实际上,像这样就可以了: | 实际上,像这样就可以了: | ||
+ | |||
<code cpp> | <code cpp> | ||
行 183: | 行 187: | ||
参考代码: | 参考代码: | ||
+ | <hidden> | ||
<code cpp> | <code cpp> | ||
#include <algorithm> | #include <algorithm> | ||
行 228: | 行 233: | ||
} | } | ||
</code> | </code> | ||
+ | </hidden> | ||
==== $O(n)$ 做法 ==== | ==== $O(n)$ 做法 ==== | ||
行 240: | 行 246: | ||
=== DC3 === | === DC3 === | ||
- | 可以参考 [[[https://wenku.baidu.com/view/5b886b1ea76e58fafab00374.html|2009]后缀数组——处理字符串的有力工具 by. 罗穗骞]]。 | + | 可以参考 [[https://wenku.baidu.com/view/5b886b1ea76e58fafab00374.html|2009 后缀数组——处理字符串的有力工具 by. 罗穗骞]]。 |
===== 后缀数组的应用 ===== | ===== 后缀数组的应用 ===== | ||
行 267: | 行 273: | ||
参考代码: | 参考代码: | ||
+ | <hidden> | ||
<code cpp> | <code cpp> | ||
#include <cctype> | #include <cctype> | ||
行 322: | 行 329: | ||
} | } | ||
</code> | </code> | ||
+ | </hidden> | ||
+ | |||
+ | ===== height 数组 ===== | ||
+ | |||
+ | ==== LCP(最长公共前缀) ==== | ||
+ | |||
+ | 两个字符串 $S$ 和 $T$ 的 LCP 就是最大的 $x$ ($x\le\min(|S|,|T|)$) 使得 $S_i=T_i(\forall1\le i\le x)$。 | ||
+ | |||
+ | 下文中以 $lcp(i,j)$ 表示后缀 $i$ 和后缀 $j$ 的最长公共前缀(的长度)。 | ||
+ | |||
+ | ==== height 数组的定义 ==== | ||
+ | |||
+ | $height[i]=lcp(sa[i],sa[i-1])$,即第 $i$ 名的后缀与它前一名的后缀的最长公共前缀。 | ||
+ | |||
+ | $height[1]$ 可以视作 $0$。 | ||
+ | |||
+ | ==== O(n) 求 height 数组需要的一个引理 ==== | ||
+ | |||
+ | $height[rk[i]]\ge height[rk[i-1]]-1$ | ||
+ | |||
+ | 证明: | ||
+ | |||
+ | 略 | ||
+ | |||
+ | ==== O(n) 求 height 数组的代码实现 ==== | ||
+ | |||
+ | 利用上面这个引理暴力求即可: | ||
+ | |||
+ | <code cpp> | ||
+ | for (i = 1, k = 0; i <= n; ++i) { | ||
+ | if (k) --k; | ||
+ | while (s[i + k] == s[sa[rk[i] - 1] + k]) ++k; | ||
+ | ht[rk[i]] = k; // height太长了缩写为ht | ||
+ | } | ||
+ | </code> | ||
+ | $k$ 不会超过 $n$,最多减 $n$ 次,所以最多加 $2n$ 次,总复杂度就是 $O(n)$。 | ||
+ | |||
+ | 未完待续 | ||
+ | |||
+ | ===== 参考链接 ===== | ||
+ | |||
+ | [[https://oi-wiki.org/string/sa/|参考链接]] |