后缀数组

利用后缀数组构造后缀树 由于蒟蒻azui前段时间忙着准备省选,并在省选中成功闷声滚大粗,博客停更了好久。。 阅读详情

题目很简单,就是给出一个字符串,把这个字符串的所有非空后缀从小到大排序后,按顺序输出后缀的第一个字符在原串中的位置。

样例

输入样例:

ababa

输出样例:

5 3 1 4 2

解释:

排好序后为:

  1. a

  2. aba

  3. ababa

  4. ba

  5. baba

暴力肯定不行啦!
这里我们使用一个叫后缀数组的东西

PS:搞懂模版还要感谢大佬zhangjianweivv的博客!

什么是后缀数组?

后缀数组为rank[i],为Suffix array的简写,表示排名为i的字符串的 编号 (PS:这里,我们简称排序后后缀的第一个字符所在的位置为 编号 )

还有一个玩意儿叫名次数组,为rank[i],表示编号为i的字符串的 排名

可以发现,rank[i]是sa[i]的逆运算,而且我们所需要的答案就是sa[i]

后缀数组怎么求?

这才是真正的步入主题啊。。ps:前面讲辣么多废话

这里我们讲倍增算法,因为好理解我菜

另当前的字符串为aabaaaab

下面这个图很清楚:

图片来源:《后缀数组–处理字符串有力工具》

  • 我们先把字符串的每个字母排序,存在rank数组里面,我们认为这是第一关键字

  • 然后我们将第一关键字每隔2k2^k2k的字符的排名作为第二关键字

  • 这时,我们使用计数排序(网上很多都说是基数排序,但其实是计数排序)将这两个关键字排序,就类似于两位数字的排序

  • 将排序后的结果作为第一关键字,然后继续循环第二,三次操作

计数排序是什么?

计数排序和基数排序很像。

先讲基数排序:

图片来源:jinkun113大佬的博客

类似于桶排序,

  • 先按个位的数字一个个放入09的桶里,再按顺序从09取出来,(当然如果你是从大到小就是9~0啦!)

  • 接着再按十位的数字一个个放入桶里,按顺序取出来,如果是两位数,这时我们得到的就是答案!

  • 以此类推,一直循环到最后一位

计数排序,就更高级了。这里优化了一下,
就是我们在基数排序所用的桶,是记录他出现的次数,然后累加(写入代码就是cnt[i]+=cnt[i-1]),这样我们得到的cnt[i]数组里就是不大于i的个数,就是他的排名了!

上代码!

我先解释一下每个变量的含义

rank[i]表示编号为i的排名 
sa[i]表示排名为i的编号 
cnt[i]计数排序的桶 
pos[i]表示当前第二关键字已经排好序时第i名第二关键字所对应的第一关键字位置
tmp[i]
排序时:表示当前排序中编号为i的排名
排序后:表示调整rank前的排名
#include<cstdio>
#include<cstring>
using namespace std;
/*
rank[i]表示编号为i的排名 
sa[i]表示排名为i的编号 
cnt[i]计数排序的桶 
pos[i]表示当前第二关键字已经排好序时第i名第二关键字所对应的第一关键字位置
tmp[i]
排序时:表示当前排序中编号为i的排名
排序后:表示调整rank前的排名
*/
char s[1200000];
int cnt[1200000],pos[1200000],sa[1200000],tmp[1200000],rank[1200000];
bool pd(int x,int y,int k){return tmp[x]==tmp[y]&&tmp[x+k]==tmp[y+k];}
void suffix(int n,int m)
{
	int i,k;
	for(i=1;i<=n;i++)rank[i]=s[i],cnt[rank[i]]++;
	for(i=1;i<=m;i++)cnt[i]+=cnt[i-1];
	for(i=n;i>=1;i--)sa[cnt[rank[i]]--]=i;//计数排序,设置好rank和sa数组 
	for(k=1;k<n;k<<=1)//k表示长度,k<<1表示k*2 
	{
		int len=0;for(i=n-k+1;i<=n;i++)pos[++len]=i;//如果第二关键字为0的话,肯定最小,我们先加入pos 
		for(i=1;i<=n;i++)if(sa[i]>k)pos[++len]=sa[i]-k;//准备好pos数组 
		
		memset(cnt,0,sizeof(cnt));
		for(i=1;i<=n;i++)tmp[i]=rank[pos[i]],cnt[tmp[i]]++;
		for(i=1;i<=m;i++)cnt[i]+=cnt[i-1];
		for(i=n;i>=1;i--)sa[cnt[tmp[i]]--]=pos[i];//更新sa数组 
		
		for(i=1;i<=n;i++)tmp[i]=rank[i];//记录之前的排名 
		
		len=1;rank[sa[1]]=1;//初始化 
		for(i=2;i<=n;i++){if(pd(sa[i],sa[i-1],k)==false)len++;rank[sa[i]]=len;}//通过sa来更新rank数组,并且去重 
		if(len==n)break;m=len; 
	}
	for(i=1;i<n;i++)printf("%d ",sa[i]);
	printf("%d\n",sa[n]);
}
int main()
{
	scanf("%s",s+1);int len=strlen(s+1);
	suffix(len,130);//'z'是122 ,为了保险设置为130
	return 0;
}
后缀数组(Suffix Array) 后缀数组(Suffix Array)标程。采用DA算法。RMQ预处理询问。 立即下载

相关推荐

《生化危机9:安魂曲》D加密免BIOS破解方案详解

数字版权管理(DRM)技术通过加密手段保护软件版权,Denuvo(D加密)作为主流方案常应用于3A游戏。其原理是通过实时验证机制阻止未授权访问,但可能影响性能表现。本文以《生化危机9》为例,解析一种免BIOS修改的D加密绕过方案,该方案通过授权启动器模拟正版验证流程,保持系统零侵入性。实测表明,该方法在GTX 1060至RTX 3070等多硬件平台均能稳定运行,支持MOD扩展且兼容Reshade画质增强,为玩家提供开箱即用的绿色版体验。

weixin_33898233的博客 925

数据结构之后缀数组

数据结构之后缀数组 1. 概述 后缀数组是一种解决字符串问题的有力工具。相比于后缀树,它更易于实现且占用内存更少。在实际应用中,后缀数组经常用于解决字符串有关的复杂问题。 本文大部分内容摘自参考资料[1][2]。 2. 后缀数组 2.1   几个概念 (1)后缀数组SA 是一个一维数组,它保存1..n 的某个排列SA[1],SA[2],……,SA[n],并且保证Suffix(SA[

leolin_的专栏 846

Ubuntu22.04中通过conda快速部署PyTorch开发环境(CPU/GPU双版本实战)

本文详细介绍了在Ubuntu22.04系统中,如何利用Conda高效部署PyTorch开发环境。文章分别提供了CPU与GPU双版本的实战教程,涵盖环境创建、镜像加速、版本匹配及深度验证等关键步骤,旨在帮助开发者快速搭建稳定、兼容的深度学习环境,从而专注于模型开发。

rose2的博客 556

后缀数组详解

后缀是指从某个位置iii开始到整个串末尾结束的一个特殊子串。字符串rrr的第iii个字符开始的后缀的表示为suffix(i)suffix(i)suffix(i),也就是suffix(i)=r[i…len(r)−1]suffix(i)=r[i…len(r)−1]后缀数组sasasa是一个一维数组,它保存1…n1\dots n1…n的某个排列sa[1。......

tanjunming2020的博客 3080

Cadence Sigrity PowerSI实战:从.brd到S参数提取的完整避坑指南

本文详细介绍了使用Cadence Sigrity PowerSI进行信号完整性分析的完整流程,从.brd文件预处理到S参数提取的关键技巧。通过实战案例和避坑指南,帮助工程师高效解决高速PCB设计中的信号质量问题,提升仿真精度和设计效率。

carrot的博客 694

PSM-DID实战指南:Stata代码解析与案例应用

本文详细解析PSM-DID方法在Stata中的实战应用,从理论到代码实现全面覆盖。通过倾向得分匹配(PSM)和双重差分(DID)的结合,有效解决政策评估中的选择偏差问题。文章提供完整的Stata命令代码、样例数据处理技巧和案例应用,帮助研究者准确评估政策效果。

vulkan6gpu的博客 792

后缀数组(Suffix Array)

啥是后缀数组?难不难? 后缀数组看上去是一个很高深,很玄妙的东西。 但首先,我们要树立一个观点:它!不难!! 实际上,他也真的不难。难的只是其中一个想法的操作。除此以外,不难。 后缀数组的概念 首先,我们需要了解一下什么是后缀 后缀,顾名思义,缀在后面的东西。在字符串中,就是缀在字符串后面的东西,大家可以联系一下英语单词中的后缀来理解。 举个例子 字符串:abaab 后缀分别有: abaab, ...

一个小渣渣的博客:) 1519

Arm Neoverse CMN-700 SLC内存系统与缓存分区技术解析

现代处理器架构中,缓存一致性协议与内存子系统设计直接影响系统性能。Arm Neoverse CMN-700采用的SLC(System Level Cache)通过16-way组相联设计实现高效数据缓存,其物理地址索引机制支持灵活的way分区配置。在软件可配置内存(OCM)模式下,SLC可作为独立内存空间使用,通过寄存器控制实现模式切换与区域锁定。缓存分区技术则通过请求源分类和way-based分配策略,满足实时性任务与吞吐量场景的不同需求。这些技术在5G基站、边缘计算等低延迟场景中具有重要应用价值,特别是C

weixin_30263073的博客 613

后缀数组 详解

字符串前缀:从字符串开头到字符串某个位置 字符串后缀:从字符串某个位置到字符串结尾 ( 原串 和 空字符串 也是 前缀(后缀)) 后缀数组:将所有后缀按字典序排序后,得到的数组 如果我们直接将每个字符串进行比较,复杂度为 O( nlogn * n ) ...

gronkie的博客 4161

【WorkBuddy专栏09】WorkBuddy多模态能力深度揭秘

【WorkBuddy专栏09】AI不止会聊天——WorkBuddy多模态能力深度揭秘

AI人人懂 2108

【Python基础】FastAPI 从入门到项目实战操作详解

【Python基础】FastAPI从入门到使用实战操作详解

congge_study的博客 441

后缀树及后缀数组

后缀树: 后缀树是一种数据结构,它支持有效的字符串匹配和查询。 一个具有m个词的字符串S的后缀树T,就是一个包含一个根节点的有向树,该树恰好带有m个叶子,这些叶子被赋予从1到m的标号。 每一个内部节点,除了根节点以外,都至少有两个子节点,而且每条边都用S的一个非空子串来标识。出自同一节点的任意两条边的标识不会以相同的词开始。后缀

E.G的专栏 2471

WIN10系统下VS2019编译CloudCompare2.12.4

CloudCompare2.12.4

点云侠的博客 3143

后缀树&后缀数组&LCP

后缀树: 字符串匹配算法一般都分为两个步骤,一预处理,二匹配。 KMP和AC自动机都是对模式串进行预处理,后缀树和后缀数组则是对文本串进行预处理。 后缀树的性质: 存储所有 n(n-1)/2 个后缀需要 O(n) 的空间,n 为的文本(Text)的长度; 构建后缀树需要 O(dn) 的时间,d 为字符集的长度(alphabet); 对模式(Pattern)的查询需要 O(dm) 时间,...

CSer 2299

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

后缀树/后缀数组

字典树:https://blog.youkuaiyun.com/hebtu666/article/details/83141560 后缀树:后缀树,就是把一串字符的所有后缀保存并且压缩的字典树。   相对于字典树来说,后缀树并不是针对大量字符串的,而是针对一个或几个字符串来解决问题。比如字符串的回文子串,两个字符串的最长公共子串等等。 比如单词banana,它的所有后缀显示到下面的。0代表从第一个字符...

少说,多做。 4435

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【后缀数组】后缀排序

最近几天有很多题目没有写,尽量补上吧。 hz2016评测《《点击访问 caioj《《点击访问 后缀数组》后缀自动机 树状数组》线段树 其实两种都是用一个特殊的简单结构,维护一部分高级算法的查询结构。后缀自动机顾名思义,就是处理后缀的啦,这道题是模板题,把数组的所有后缀按照大到小排序。具体还是看代码注释吧,结合代码会比较好理解。 #include #include

正汰的学习笔记 965

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

最详细的后缀数组

写在前面: 多余的我就不提了,只是觉得网上的博客吧流程,每个数组存的是下标还是值,都讲的不是很清楚(让我这种蒟蒻很是困扰) 清爽代码: #include&amp;amp;amp;lt;iostream&amp;amp;amp;gt; #include&amp;amp;amp;lt;cstdio&amp;amp;amp;gt; #include&amp;amp;amp;lt;cstring&amp;amp;amp;gt;

LZH的博客 5276

后缀数组-后缀排序

后缀数组-一个可以解决多种字符串中字串问题的优秀算法

Mint_hexagram的博客 1196

后缀数组的实现

后缀数组的生成

Gikor 1478

字符串处理【后缀数组】 - 原理2 后缀数组

字符串处理【后缀数组】 - 原理2 后缀数组

代码改变世界 1647
上一篇: 表达式
下一篇: 修改串
candy_c
博客等级 码龄11年 7粉丝 23原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值