后缀树与后缀数组简介及代码模板 ← AcWing 2715-编程知识

后缀树与后缀数组简介及代码模板 ← AcWing 2715

【题目来源】
https://www.acwing.com/problem/content/2717/

【题目描述】
给定一个长度为 n 的字符串,只包含大小写英文字母和数字。
将字符串中的 n 个字符的位置编号按顺序设为 1∼n。
并将该字符串的 n 个非空后缀用其起始字符在字符串中的位置编号表示。
现在要对这 n 个非空后缀进行字典序排序,并给定两个数组 SA 和 Height。
排序完成后,用 SA[i] 来记录排名为 i 的非空后缀的编号,用 Height[i] 来记录排名为 i 的非空后缀与排名为 i−1 的非空后缀的最长公共前缀的长度(1≤i≤n)。
特别的,规定 Height[1]=0。
请你求出这两个数组。

【输入格式】
共一行,包含一个长度为 n 的仅包含大小写英文字母或数字的字符串。

【输出格式】
第一行包含 n 个整数,表示 SA 数组。
第二行包含 n 个整数,表示 Height 数组。

【数据范围】
1≤n≤10^6

【输入样例】
abababab

【输出样例】
7 5 3 1 8 6 4 2
0 2 4 6 0 1 3 5

【后缀树及后缀数组简介】

后缀(Suffix):字符串的后缀是指从字符串某个位置开始到末尾的所有子串。例如,字符串 s[]="abcdefg" 的后缀为 s[0]="abcdefg"、s[1]="bcdefg"、s[2]="cdefg"、s[3]="defg"、s[4]="efg"、s[5]="fg"、s[6]="g" 等。

后缀树(Suffix Tree):将字符串的所有后缀子串用字典树的方法建立的树。换句话说,后缀树的本质是把一个长度为 n 的字符串拆成 n 个后缀子串,然后按字典序来构造。后缀树的根结点为空,后缀树中每个后缀子串的末尾用符号 $ 表示
例如,字符串 s[]="banana" 的后缀为 s[0]="banana"、s[1]="anana"、s[2]="nana"、s[3]="ana"、s[4]="na"、s[5]="a",其对应的后缀树如图所示。
 



● 长度为 n 的字符串,其 n 个后缀子串的长度分别为 n,n-1,n-2,……,2,1,总长度为 n(n+1)/2。可见,后缀树的空间复杂度比较差,为 O(n^2)。故引入后缀数组 sa (Suffix Array)来代替后缀树。

后缀数组 sa(Suffix Array):后缀数组 sa 的值就是将字符串的所有后缀子串按字典序排序后对应的原始下标。
例如,字符串 s[]="banana" 的后缀为 s[0]="banana"、s[1]="anana"、s[2]="nana"、s[3]="ana"、s[4]="na"、s[5]="a",其对应的后缀数组 sa[]={5,3,1,0,4,2}。求解过程如下图所示。

后缀数组元素 sa[i],是原字符串中从第 i 个位置开始的后缀子串(下标从 0 开始)。例如,在上图所示后缀数组 sa 中,sa[1]=3,表示排名 1 的子串,是原字符串 banana 中从第 1 个位置开始的后缀子串,即 ana。

● 在后缀数组的代码实现中,有 3 个关键的数组:后缀数组 sa[]、名次数组 rk[]、高度数组 height[]。其中,sa[] 与 rk[] 是一一对应关系,互为逆运算。
由 sa[] 数组推出 rk[] 数组在实战中常用
由 rk[] 数组推出 sa[] 数组的代码如下所示:

for(int i=0; i<n; i++) sa[rk[i]]=i;

由 sa[] 数组推出 rk[] 数组的代码如下所示:

for(int i=0; i<n; i++) rk[sa[i]]=i;

例如,由上文已知,字符串 s[]="banana" 的后缀为 s[0]="banana"、s[1]="anana"、s[2]="nana"、s[3]="ana"、s[4]="na"、s[5]="a",其对应的后缀数组 sa[]={5,3,1,0,4,2}。
据 sa[] 数组推出 rk[] 数组的代码
rk[sa[i]]=i 可得:
rk[sa[
0]]=rk[5]=0
rk[sa[1]]=rk[3]=1
rk[sa[2]]=rk[1]=2
rk[sa[3]]=rk[0]=3
rk[sa[4]]=rk[4]=4
rk[sa[5]]=rk[2]=5
由上显见,rk[i] 的值为原字符串的第 i 个后缀子串,在原字符串所有后缀子串按字典序排序后,其所处的位序

【算法代码】

#include <bits/stdc++.h>
using namespace std;const int maxn=1e6+5;//sa[i] 表示字典序排名为 i 的后缀处于原字符串所有后缀的位序
//rk[i] 表示原字符串第 i 个后缀的字典序排名
//height[i] 表示排名第 i 的后缀和排名第 i - 1 的后缀的最长公共前缀
//fi[i] 表示第 i 个后缀的第一关键字
//se[i] 表示第 i 个后缀的第二关键字
//c[i] 表示关键字为 i 的数的个数
int sa[maxn],rk[maxn];
int height[maxn];
int fi[maxn],se[maxn],c[maxn];char s[maxn];
int n,m;void get_sa() {for(int i=1; i<=n; i++) c[fi[i]=s[i]]++;for(int i=2; i<=m; i++) c[i]+=c[i-1]; //prefix sumfor(int i=n; i>=1; i--) sa[c[fi[i]]--]=i;for(int k=1; k<=n; k<<=1) {//Radix Sort based on 2nd keyint num=0;for(int i=n-k+1; i<=n; i++) se[++num]=i;for(int i=1; i<=n; i++)if(sa[i]>k) se[++num]=sa[i]-k;//Radix Sort based on 1st keyfor(int i=1; i<=m; i++) c[i]=0;for(int i=1; i<=n; i++) c[fi[i]]++;for(int i=2; i<=m; i++) c[i]+=c[i-1];for(int i=n; i>=1; i--) sa[c[fi[se[i]]]--]=se[i], se[i]=0;//Discretize all sorted suffixes according to the first 2K charactersswap(fi,se);fi[sa[1]]=1, num=1;for(int i=2; i<=n; i++) {if(se[sa[i]]==se[sa[i-1]] && se[sa[i]+k]==se[sa[i-1]+k]) fi[sa[i]]=num;else fi[sa[i]]=++num;}if(num==n) break;m=num;}
}void get_height() {for(int i=1; i<=n; i++) rk[sa[i]]=i;for(int i=1, k=0; i<=n; i++) {if(rk[i]==1) continue;if(k) k--;int j=sa[rk[i]-1];while(i+k<=n && j+k<=n && s[i+k]==s[j+k]) k++;height[rk[i]]=k;}
}int main() {scanf("%s", s+1);n=strlen(s+1);m=122; //ASCII of 'z' is 122get_sa();get_height();for(int i=1; i<=n; i++) printf("%d ",sa[i]);printf("\n");for(int i=1; i<=n; i++) printf("%d ", height[i]);return 0;
}/*
in:
ababababout:
7 5 3 1 8 6 4 2
0 2 4 6 0 1 3 5
*/




【参考文献】
https://www.acwing.com/solution/content/163123/
https://www.acwing.com/solution/content/58924/

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/688435.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

挖了谷歌一个 XSS 漏洞,获奖三千美金

大家好&#xff0c;我是楷鹏。 程序员 Matan 挖到了一个 XSS 漏洞并报告给谷歌&#xff0c;奖励 3133.7 美金&#xff08;约合人民币 22666 元&#xff09; 这是谷歌 Bug Hunter 的奖励规则&#xff1a; &#x1f449; 图片来自 https://bughunters.google.com/about/rules/…

源代码防泄密的重要性

​源代码”作为互联网企业的核心资产之一&#xff0c;其安全性至关重要。源代码泄露不仅可能导致企业丧失技术优势&#xff0c;还可能引发知识产权纠纷、增加竞争对手的市场竞争力&#xff0c;甚至可能被用于恶意目的&#xff0c;如开发恶意软件等。因此&#xff0c;保护源代码…

十天学会单片机可能吗?单片机入门需要多久?

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 十天学“会”单片机&#xf…

启用dell服务器的iDRAC

插网线 观察到 dell服务器背板左侧有一个网口&#xff0c;标有iDRAC字样&#xff0c;使用网线将该网口和网段所在的交换机连接起来。 网络配置 重启计算机&#xff0c;依照屏幕显示按F2进入SystemSetup。选择iDRACsettings – Network&#xff0c;需要改动的如下&#xff08;现…

微信小程序按钮去除边框线

通常我们去掉按钮边框直接设置 border:0 但是在小程序中无效&#xff0c;设置outline:none也没用&#xff0c;当然可能你会说加权重无效 实际上该样式是在伪元素::after内&#xff0c;主要你检查css 还看不到有这个关系&#xff0c;鹅厂就是坑多 类样式::after {border: non…

半小时搞懂STM32面经知识点——系统架构与启动流程

1.Cortex-M系统 1.1系统结构 1.处理器核心&#xff1a; Cortex-M3 2.存储器系统&#xff1a; Flash&#xff0c;SRAM&#xff0c;FSMC等 3.总线接口&#xff1a; 核心通过总线接口与外设设备和存储器进行通信。 总线矩阵&#xff1a;总线矩阵是一种硬件结构&#xff0c;用于连…

kali安装及替换源

一、安装及简单配置 1.安装&#xff1a;地址就不贴了&#xff0c;自己打一下就好 2.虚拟机中打开kali 3.替换包源 (1)使用指令打开/etc/apt/sources.list mousepad /etc/apt/sources.list (2)将内容替换成阿里云源 deb http://mirrors.aliyun.com/kali kali-rolling main n…

如何让组织充满活力?你需要做好这七步

组织活力&#xff0c;通俗点说就是&#xff1a; 从竞争对手角度看&#xff0c;组织活力强的组织能做到竞争对手做不到的事情&#xff1b; 从客户角度看&#xff0c;组织活力强的组织&#xff0c;客户感受好&#xff1b; 从员工角度看&#xff0c;组织活力强的组织&#xff0c…

干货分享:AI知识库-从认识到搭建

随着知识库的出现&#xff0c;人工智能也逐渐加入进来&#xff0c;形成了“AI知识库”。也许将AI和知识库拆开&#xff0c;你能理解是什么意思&#xff0c;但是当两个词结合在一起时&#xff0c;你又真的能理解它是做什么的吗&#xff1f;这就是今天我们要来聊的话题&#xff0…

企业微信hook接口协议,ipad协议http,新增联系人移除联系人到聊天标签

新增联系人移除联系人到聊天标签 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"2b0863724106a1160212bd1ccf025295","tagids":[10133101616638504 //标签id数组可以打多个空数组…

Vue3的CRUD模版(附Demo)

目录 前言模版 前言 用惯Vue2之后&#xff0c;在碰Vue3后&#xff0c;整体还是有所区别 此文主要做一个回顾总结 假设界面如下&#xff1a; 可CRUD&#xff0c;对应的新增 添加一些必选项&#xff1a; 其中数据库的设计如下&#xff1a; 模版 对应需要注意参数位置、初始…

排序1——直接插入排序,希尔排序,选择排序,堆排序

1.排序的概念及其运用 1.1排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录…

idea中使用git拉取代码详细操作

注意&#xff1a;解决 Git拉取代码和本地代码丢失问题请点这里查看 以textGit文件为例&#xff1a; 下图&#xff1a;本地刚拉取远程的代码 git上的代码 1、在本地对代码进行修改 2、在git上对代码进行修改&#xff0c;模拟其他人对此文件的提交修改 3、拉取远程代码 4、合并自…

智慧校园的主要功能是什么

随着信息化的发展&#xff0c;智慧校园的应用已经屡见不鲜。智慧校园是新技术与新科技落地的典型案例。智慧校园完善了校园信息化建设体系&#xff0c;推动了教育水平的提升&#xff0c;以下是智慧校园实现的几个比较典型的功能&#xff1a; 1.数字化办公 毋庸置疑&#xff0…

Remix Client/Server 架构

Remix 框架是服务端渲染架构&#xff0c;当路由请求时生成 HTML 并返回浏览器。这种 SSR 是如何实现的呢&#xff1f;如果不使用 Remix 这种框架&#xff0c;可以在服务器段启动一个无头浏览器进行页面渲染并返回&#xff0c;代价就是要在服务器上启动一个 Chrome 服务&#xf…

第12节 第二种shellcode编写实战(1)

我最近在做一个关于shellcode入门和开发的专题课&#x1f469;&#x1f3fb;‍&#x1f4bb;&#xff0c;主要面向对网络安全技术感兴趣的小伙伴。这是视频版内容对应的文字版材料&#xff0c;内容里面的每一个环境我都亲自测试实操过的记录&#xff0c;有需要的小伙伴可以参考…

三层交换机与路由器连通上网实验

三层交换机是一种网络交换机&#xff0c;可以实现基于IP地址的高效数据转发和路由功能&#xff0c;通常用于大型企业、数据中心和校园网络等场景。此外&#xff0c;三层交换机还支持多种路由协议&#xff08;如OSPF、BGP等&#xff09;&#xff0c;以实现更为复杂的网络拓扑结构…

2024年第九届“数维杯”大学生数学建模挑战赛B题

第一个问题为&#xff1a;正己烷不溶物对热解产率是否产生显著影响&#xff1f; 第一个问题&#xff1a;正己烷不溶物(INS)对热解产率是否产生显著影响&#xff1f; 解析&#xff1a;正己烷不溶物(INS)主要是由生物质和煤中的非挥发性物质组成&#xff0c;它们在共热解过程中会…

通信指挥类装备(多链路聚合设备)-应急通信指挥解决方案

现场通信指挥系统是一种功能全面的便携式音视频融合指挥通信平台&#xff0c;可实现现场应急救援指挥、多种通信手段融合、现场通信组网等功能&#xff0c;是现场指挥系统的延伸。 多链路聚合设备&#xff0c;是一款通信指挥类装备&#xff0c;具有 4G/5G&#xff0c;专网&…

Cloudera的简介及安装部署

简介 Cloudera是一家位于美国的软件公司&#xff0c;成立于2008年&#xff0c;专注于为企业客户提供基于Apache Hadoop的软件、支持、服务以及培训。Cloudera的开源Apache Hadoop发行版&#xff0c;即Cloudera Distribution including Apache Hadoop&#xff08;CDH&am…