当前位置: 首页 > news >正文

后缀数组 Suffix Array

前言

去年省选前就想搞的东西,也算是在省选前搞完了。(雾)

后缀数组

基本定义

后文中使用“后缀 \(i\)”指代 \(S[i:n]\)\(n\)\(|S|\)

\(sa_i\) 表示字典序第 \(i\) 小的后缀,\(rk_i\) 表示后缀 \(i\) 的字典序排名。二者显然互逆。

实现

\(O(n\log^2 n)\)

倍增思想。首先对原串所有长度为 \(1\) 的子串按字典序排序得到 \(sa,rk\),然后倍增长度 \(w\)

当处理到 \(|S|=2w\) 的子串时,我们已经拥有了 \(|S|=w\) 的所有子串的 \(sa,rk\) 信息。考虑将每个 \(|S|=2w\) 的子串分为前后两个 \(|S'|=w\) 的子串(不够的留空,空字符字典序最小),这样每个串就有了第一第二两个关键字,同时所有关键字之间的相对大小关系是已知的。我们直接 \(O(n\log n)\) 地 sort 一遍即可。sort 之后根据得到的 \(sa\) 得到新的 \(rk\) 数组,记得去重。

因为只会跑 \(\log n\) 次,故而复杂度 \(O(n\log^2 n)\)

\(O(n\log n)\)

沿用两只老哥的做法,发现复杂度瓶颈在于每次 sort 的复杂度。考虑到要排序的值域在 \(O(n)\) 级别,考虑使用基数排序,同时去重容易 \(O(n)\) 实现,于是单轮复杂度降到 \(O(n)\),复杂度 \(O(n\log n)\)。基排是稳定排序,由于我们是 cnt-- 倒着得到位置,所以只需按第二关键字倒序枚举填入即可完成排序。

但这样常数太大了,考虑优化。注意到对第二关键字的排序实际无需搞基排,因为原 \(sa\) 数组实际上已经给所有第二关键字排好序了,我们只需要将所有第二关键字为空字符的节点挪到 \(sa\) 数组最前面即可。

另一个小优化是每次将值域更新为 \(rk\) 去重后的大小,当值域为 \(n\) 时整个数组已经有序了可以直接结束。

int sa[N],rk[N],cnt[N],id[N],ok[N];
void SA(string s){int n=s.size(),m=127;s=' '+s;rep(i,1,n)++cnt[rk[i]=s[i]];rep(i,1,m)cnt[i]+=cnt[i-1];rep(i,1,n)sa[cnt[rk[i]]--]=i;for(int w=1;w==1||m<n;w<<=1){int cur=0;rep(i,n-w+1,n)id[++cur]=i;rep(i,1,n)if(sa[i]>w)id[++cur]=sa[i]-w;rep(i,1,m)cnt[i]=0;rep(i,1,n)++cnt[rk[i]];rep(i,1,m)cnt[i]+=cnt[i-1];per(i,n,1)sa[cnt[rk[id[i]]]--]=id[i];m=0;rep(i,1,n)ok[i]=rk[i];rep(i,1,n){if(ok[sa[i]]!=ok[sa[i-1]]||sa[i]>n-w||sa[i-1]>n-w||ok[sa[i]+w]!=ok[sa[i-1]+w])++m;rk[sa[i]]=m;}}
}
http://www.jsqmd.com/news/440157/

相关文章:

  • MES系统部署
  • 5分钟学会 快速实现OpenClaw接入飞书机器人【保姆级教程】
  • Nginx使用05:使用后端鉴权接口限制静态资源的访问
  • 2026年知识产权交易优质平台推荐,解决你选择难题的最佳榜单 - 睿易优选
  • 主流渲染软件盘点及行业优选云渲染推荐
  • UE5.3 Compute Shader 完整教程(从零开始)
  • 2026年口碑好的托盘立体库公司推荐:全自动立体库源头工厂推荐 - 品牌宣传支持者
  • CAN通信:STM32F1xx_hal_can入门实战详解 - 教程
  • 2026年比较好的软芯控制电缆公司推荐:低烟无卤控制电缆厂家综合实力对比 - 品牌宣传支持者
  • 施耐德页面显示图片4-一种简单的方法(剪贴板粘贴图片)
  • 没有PoE 交换机,也能做 PoE?工程改造的 3 种方案解析
  • PanelAI子服务器管理模块实测:熊哥演示防火墙入/出站规则+项目/模型列表同步+早鸟票体验进度,2026开源前瞻
  • 一次选对 PoE 交换机:6 大工程维度拆解室内 / 户外 / 工业核心差异
  • 在华为arm Linux机器上测试ollama 0.17.6运行qwen3.5小模型
  • 视频编辑软件会声会影(Corel VideoStudio)2023旗舰版
  • 强化学习项目完整流程
  • 1143.最长公共子序列
  • Javascript迭代器与生成器
  • 2026年靠谱的碳纤维编织布公司推荐:碳纤维预浸料/碳纤维复合皮革/碳纤维精密结构件可靠供应商推荐 - 品牌宣传支持者
  • 力诺药包预灌封注射器产品通过ISO13485医疗器械管理体系认证
  • 中英(伦敦)航线机票预订十大FAQ详解:避坑指南+专业解答,出行认准北京圣擎航空 - 今日又土又金
  • CCF推荐期刊会议列表(2026第七版)——《中国计算机学会推荐国际学术会议和期刊目录》
  • 2026企业高品质官网定制服务商榜单:擅长品牌数字化重塑与用户体验升级团队深度测评 - 资讯焦点
  • 维普AIGC检测率太高?嘎嘎降AI一键搞定(附详细教程)
  • Flutter 三方库 file_picker 的鸿蒙化适配指南 - 让文件选择不再困难、多类型文件过滤实战、鸿蒙级沙箱文件访问全攻略
  • 2026植物工厂优质厂家推荐榜聚焦智能节能方案 - 优质品牌商家
  • 2026年质量好的多孔钻床品牌推荐:非标攻丝多孔钻床优质供应商推荐 - 品牌宣传支持者
  • 减速器综合性能试验机精度实测 PK 高精准品牌答案揭晓 - 品牌推荐大师
  • 中澳航线旅客最关心的10个机票预订问题,北京圣擎航空为您一一解答! - 今日又土又金
  • 2026好用的工作手机推荐——这款实用便宜的工作手机成行业首选 - 资讯焦点