后缀数组

后缀数组

定义#

sai 表示排名为 i 的后缀起点下标。

rki 表示后缀 i 的排名。

求 SA#

O(nlog2n) 的基本思路是倍增。

假设已知 i 开头长为 l 的串的排名为 rki,只需要根据 rkirki+l 进行双关键字排序就能得到 i 开头长为 2l 的串的排名。每一次长度能倍增。最后得到每一个位置开头,长度为 l>n 的串的排名,相当于后缀的排名。

使用 sort 直接进行双关键字排序可以做到 O(nlog2n),使用基数排序可以优化至 O(nlogn)

有几个小优化,优化较为明显。首先按照第二关键字排序,对于开头在 [nl+1,n] 的串,它们的 i+l 超过了 n,所以第二关键字为 0,按照第二关键字排序之后一定在最前面。剩下的部分,若 sai>w,则插入 saiw 这个位置。也就是说由于上次已经对第二关键字的所有串排序了,直接插入即可。

实现有一些技巧,可以看看 OI-Wiki 上的代码。

height 数组#

下文中 lcp(i,j) 表示后缀 i 和后缀 j 的最长公共前缀。

heighti 定义为 lcp(sai,sai1)

引理:height[rki]height[rki1]1。人话:后缀 i 与其前一名的最长公共前缀长度 至少i1 后缀与其前一名的最长公共前缀长度减一。

证明:

height[rki1]1,则右边不超过 0,显然成立。

否则,如图:

img

绿色部分即为 i1 后缀 height[rki1],由定义知,绿色部分后一个字符 X<Y

A 串红色部分 i 后缀。由于 X<Y,故 B 串红色部分字典序必小于 A 串红色部分。

B 红为 A 红前一名,引理成立。否则考虑中间夹着的串,容易发现,引理仍成立。

故求 height 数组可以 O(n),具体地,利用引理暴力求,由于每一次只会减一,总共只能减 n 次,也就只能加 O(n) 次了。

作者:Terminator-Line

出处:https://www.cnblogs.com/Terminator-Line/p/18718935

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Terminator-Line  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示