题目:后缀排序

什么是后缀数组?他主要包含两个数组:sa和rk。

其中sa[i]表示将字符串后缀排序后第i小的编号,rk[i]表示后缀i的排名。

显然sa[rk[i]]=i,rk[sa[i]]=i。

例如字符串aba,他的后缀aba,ba,a,排序后a,aab,ab,此时

| i | 1 | 2 | 3 |

| sa | 3 | 1 | 2 |

| rk | 2 | 3 | 1 |

观察上面给出的式子,发现都成立。

那如何求后缀数组呢,最简单的方法是直接排序,不要以为时间复杂度是O(nlogn),字符串比较还有一层O(n),所以总时间复杂度是O(n^2logn)的,显然不行。

既然快排不行,那用别的排序咯,我们发现字符个数很少,因此采用基数排序,但是朴素的基数排序是O(n^2)更慢了,因此这里使用倍增优化,每次枚举范围扩大一倍,为什么可行?

试想一下,如果对于基数排序,我们也可以通过压位,以10,100,甚至更多为一个单位,显然答案不会改变,只是效率的改变罢了,因此这里同理可以得到。

具体讲一下做法,设字符串s,先求出所有s[i]的排名,这就是最基础的对应关系,也就是以一个字符为基准的方法个数,接下来就是枚举长度了,每次求出二元组(k1[i],k2[i])表示排序的两个关键字,以k2[i]为关键字排序,然后再以k1[i]为关键字排,排序号后,求出所有数的排名,如果最大的编号为字符串长度,那么就说明已经完成了后缀排序,此时sa和rk中存储的就是最开始所说的内容。

时间复杂度O(nlogn),一个比较优秀的算法。

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int N=1e6+5;
using namespace std;
int n,cnt[N],rk[N],psa[N],sa[N],k1[N],k2[N],m;
char s[N];
int main()
{
scanf("%s",s);
n=strlen(s);
m=max(n,300);
for(int i=0;i<n;i++)
cnt[(int)s[i]]++;
for(int i=1;i<m;i++)
cnt[i]+=cnt[i-1];
for(int i=0;i<n;i++)
rk[i]=cnt[(int)s[i]]-1;
for(int w=1;w<n;w<<=1)
{
for(int i=0;i<n;i++)
{
if(i+w>=n)
k2[i]=0;
else
k2[i]=rk[i+w];
k1[i]=rk[i];
}
for(int i=0;i<n;i++)
cnt[i]=0;
for(int i=0;i<n;i++)
cnt[k2[i]]++;
for(int i=1;i<m;i++)
cnt[i]+=cnt[i-1];
for(int i=n-1;i>=0;i--)
psa[--cnt[k2[i]]]=i;
for(int i=0;i<n;i++)
cnt[i]=0;
for(int i=0;i<n;i++)
cnt[k1[i]]++;
for(int i=1;i<m;i++)
cnt[i]+=cnt[i-1];
for(int i=n-1;i>=0;i--)
sa[--cnt[k1[psa[i]]]]=psa[i];
int tmp=1;
rk[sa[0]]=1;
for(int i=1;i<n;i++)
if(k1[sa[i]]==k1[sa[i-1]] && k2[sa[i]]==k2[sa[i-1]])
rk[sa[i]]=tmp;
else
rk[sa[i]]=++tmp;
if(tmp==n)
break;
}
for(int i=0;i<n;i++)
printf("%d ",sa[i]+1);
return 0;
}

2022春每日一题:Day 13的更多相关文章

  1. <每日一题>题目13:列表的简单问题

    ''' 分析: python赋值是通过指针来进行的. 很显然第一.三.四次调用都指向同一个列表,并未完成清空, 第二次调用只是指向了另一个列表,也未完成清空,很显然结果是累计的 结果: [0, 1] ...

  2. CISP/CISA 每日一题 13

    监控信息系统人员所提供服务的效率和效果的工具: 1.例外报告:识别所有没有成功完成的或出了故障的应用 2.作业重运行报告:大多数异常终止作业都会导致重起 3.操作员问题报告:记录计算机运行问题及解决方 ...

  3. 老男孩IT教育-每日一题汇总

    老男孩IT教育-每日一题汇总 第几天 第几周 日期 快速访问链接 第123天 第二十五周 2017年8月25日 出现Swap file….already exists以下错误如何解决? 第122天 2 ...

  4. PL/SQL Challenge 每日一题:2014-3-14 11gR2中带RELIES_ON子句的RESULT_CACHE函数

    PL/SQL Challenge 每日一题:2014-3-14 11gR2中带RELIES_ON子句的RESULT_CACHE函数 最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可 ...

  5. CISP/CISA 每日一题 五

    CISA 每日一题(答) 信息系统审计师要确认系统变更程序中的: 1.变更需求应有授权.优先排序及跟踪机制: 2.日常工作手册中,明确指出紧急变更程序: 3.变更控制程序应同时为用户及项目开发组认可: ...

  6. 「每日一题」有人上次在dy面试,面试官问我:vue数据绑定的实现原理。你说我该如何回答?

    关注「松宝写代码」,精选好文,每日一题 ​时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 来源:原创 一.前言 文章首发在「松宝写代码」 2020. ...

  7. [每日一题]面试官问:谈谈你对ES6的proxy的理解?

    [每日一题]面试官问:谈谈你对ES6的proxy的理解? 关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...

  8. 【JavaScript】Leetcode每日一题-二叉搜索树的范围和

    [JavaScript]Leetcode每日一题-二叉搜索树的范围和 [题目描述] 给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和. 示例1: 输入: ...

  9. 【python】Leetcode每日一题-寻找旋转排序数组中的最小元素

    [python]Leetcode每日一题-寻找旋转排序数组中的最小元素 [题目描述] 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组.例如,原数组nums ...

  10. 【JavaScript】【dp】Leetcode每日一题-解码方法

    [JavaScript]Leetcode每日一题-解码方法 [题目描述] 一条包含字母 A-Z 的消息通过以下映射进行了 编码 : 'A' -> 1 'B' -> 2 ... 'Z' -& ...

随机推荐

  1. iOS WebRTC 点对点实时音视频流程介绍

    前言 公司某个项目需要接入音视频即时通讯, 功能类似微信的拨打视频通话,语音通话的场景.那么对于音视频通讯会用到什么技术呢?没错,它就是 WebRTC . 什么是WebRTC WebRTC,名称源自网 ...

  2. xtrabackup增量备份MySQL-5.7操作说明

    下载工具 本方法利用xtrabackup二进制包,版本是2.4.26 # 从官网下载二进制包:wget https://downloads.percona.com/downloads/Percona- ...

  3. 基于Vue的前端UI组件库的比对和选型

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 由于录制视频的需要,要做前端UI组件库的选型.平时国内外也见了不少基于Vue的UI ...

  4. 第二章 Kubernetes快速入门

    一.四组基本概念 Pod/Pod控制器: Name/Namespace: Label/Label选择器: Service/Ingress. 二.Pod/Pod控制器 2.1 Pod Pod是K8S里能 ...

  5. vacuum和vacuum full的处理过程

    对于数据库系统的并发控制,KingbaseES采用MVCC(多版本并发控制)进行处理. 这种机制有一个缺点,就是随着时间的推移,数据文件中积累的dead tuples会越来越多. 怎么去清理这些dea ...

  6. 函数索引引用的函数必须是immutable类型

    用户在使用中,可能会用到基于函数的索引,但是函数是非 immutable 类型的,导致函数索引无法创建.如: test=# create index ind_t1 on t1(to_char(crea ...

  7. Taurus.MVC 微服务框架 入门开发教程:项目集成:6、微服务间的调用方式:Rpc.StartTaskAsync。

    系统目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ...

  8. 从云AK泄露利用看企业特权管理

    从云AK泄露利用看企业特权管理 目录 - 缘起 - 当前主流AK泄露检测方式 - 防止AK滥用的关键要素? - 哪些算特权账号管理? - 如何做特权账号管理? - 特权管理与堡垒机.IAM.零信任的关 ...

  9. P1829 [国家集训队]Crash的数字表格

    P1829 [国家集训队]Crash的数字表格 原题传送门 前置芝士 莫比乌斯反演 乘法逆元 数论分块 正文 //补充:以下式子中的除法均为整除 由题目可以得知,这道题让我们所求的数,用一个式子来表达 ...

  10. CentOS无法识别NTFS格式U盘完美解决方案

    问题描述:CentOS上无法识别NTFS格式的U盘 解决方案: # 进入yum目录 cd /etc/yum.repos.d # 下载阿里的epel wget http://mirrors.aliyun ...