算法竞赛进阶指南——后缀数组
后缀数组
后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围。
在本题中,我们希望使用快排、Hash与二分实现一个简单的O(nlog2n)的后缀数组求法。
详细地说,给定一个长度为 n 的字符串S(下标 0~n-1),我们可以用整数 k(0≤k<n) 表示字符串S的后缀 S(k~n-1)。
把字符串S的所有后缀按照字典序排列,排名为 i 的后缀记为 SA[i]。
额外地,我们考虑排名为 i 的后缀与排名为 i-1 的后缀,把二者的最长公共前缀的长度记为 Height[i]。
我们的任务就是求出SA与Height这两个数组。
输入格式
输入一个字符串,其长度不超过30万。
字符串由小写字母构成。
输出格式
第一行为数组SA,相邻两个整数用1个空格隔开。
第二行为数组Height,相邻两个整数用1个空格隔开,我们规定Height[1]=0。
输入样例:
ponoiiipoi
输出样例:
9 4 5 6 2 8 3 1 7 0
0 1 2 1 0 0 2 1 0 2
说实话看到这道题的时候真的是一脸懵,这东西咋用hash,二分,快排。
后来找了些博客看,终于理解其中的思路了,
一、先记录整条的hash值。
二、用一个sort函数,自定义cmp。
三、通过二分确定两个后缀字符之间的前缀相同字母。
这道题写这篇题解的时候又重新去写了一遍,感觉真的难。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef unsigned long long ull;
const int base = 131;
const int N = 3e5 + 10;
char str[N];
ull h[N], p[N];
int sa[N], n;
ull gethash(int l, int r) {//得到某一段的hash值return h[r] - h[l - 1] * p[r - l + 1];
}
int sumsub(int a, int b) {int l = 0, r = min(n - a + 1, n - b + 1);//取最小的。while(l < r) {//二分。int mid = (l + r + 1) >> 1;if(gethash(a, a + mid - 1) != gethash(b, b + mid - 1)) r = mid - 1;else l = mid;}return r;
}
bool cmp(int a, int b) {int l = sumsub(a, b);//两个的相同前缀长度。int x = a + l > n ? - 1e9 : str[a + l];如果有一个单词都是前缀,防止发生数组越界。int y = b + l > n ? - 1e9 : str[b + l];return x < y;
}
int main() {scanf("%s", str + 1);//从第一个字符开始可以避免hash的边界问题。n = strlen(str + 1);p[0] = 1;for(int i = 1; i <= n; i++) {h[i] = h[i - 1] * base + str[i] - 'a' + 1;p[i] = p[i - 1] * base;sa[i] = i;}sort(sa + 1, sa + n + 1, cmp);//对下标进行排序。for(int i = 1; i <= n; i++) printf("%d%c", sa[i] - 1, i == n ? '\n' : ' ');printf("0 ");for(int i = 2; i <= n; i++) printf("%d%c", sumsub(sa[i], sa[i - 1]), i == n ? '\n' : ' ');return 0;
}
这个算法耗时还是非常长的,并不是真正的能用的算法,但是这个写法的综合力度还是比较高的,思想还是可以借鉴的。
算法竞赛进阶指南——后缀数组相关推荐
- 中位数--《算法竞赛进阶指南》(货仓选址和七夕祭问题详解)
中位数 今天又和大家见面了啦~ 依旧是 <算法竞赛进阶指南>的学习哦~ 中位数(Median)又称中值,统计学中的专有名词,是按顺序排列的一组数据中居于中间位置的数,代表一个样本.种群或概 ...
- 《算法竞赛进阶指南》打卡-基本算法-AcWing 93. 递归实现组合型枚举:递归与递推、dfs、状态压缩
文章目录 题目解答 题目链接 题目解答 分析: 此题和笔者另一篇博文很像,只不过是限定了个数.<算法竞赛进阶指南>打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归.二进 ...
- 《算法竞赛进阶指南》数论篇
<算法竞赛进阶指南>数论篇(1)-最大公约数,素数筛,欧拉函数,同余,欧拉定理,BSGS <算法竞赛进阶指南>数论篇(1)-最大公约数,素数筛,欧拉函数,同余,欧拉定理,BSG ...
- 《算法竞赛进阶指南(by 李煜东)》习题题解 集合
又是笔者给自己挖的大坑. 这里是李煜东所著<算法竞赛进阶指南(by 李煜东)>的习题题解集合. 有任何错误请在对应文章下反馈或联系 nicest1919@163.com ,谢谢 qwq 从 ...
- CH5202 自然数拆分Lunatic版(算法竞赛进阶指南,完全背包)
算法竞赛进阶指南,278页,完全背包 本题要点: 1.把完全背包的代码改改即可.常规的完全背包: 有n个物品,每个物品的体积是v[i], 价值是w[i], 求装到大小为m的大背包,能获得的最大价值(每 ...
- 金字塔(算法竞赛进阶指南)
虽然探索金字塔是极其老套的剧情,但是有一队探险家还是到了某金字塔脚下. 经过多年的研究,科学家对这座金字塔的内部结构已经有所了解. 首先,金字塔由若干房间组成,房间之间连有通道. 如果把房间看作节点, ...
- AcWing 122. 糖果传递【贪心】【《算法竞赛进阶指南》,微软面试题 , HAOI2008】
AcWing 122. 糖果传递 一.题目链接 二.题目分析 (一)算法标签 (二)解题思路 三.AC代码 四.其它题解 一.题目链接 AcWing 122. 糖果传递 进阶题目 AcWing 105 ...
- 算法竞赛进阶指南 骑士放置
4: 最大独立集 :选出最多的点,使得选出的点之间没有边. 求最大独立集:选出最小的点可以破坏所有的边 <==>最小点覆盖 <==>最大匹配数. 假设最大匹配数为m,共有n个点 ...
- 算法竞赛进阶指南 萌新入门!
算法竞赛进阶指南 文章目录 算法竞赛进阶指南 前言 一.介绍本书 二.如何阅读本书 三.总结 **笔记思路和结构 ** 算法竞赛进阶指南 这篇文章就简单的写一下吧! 前言 作为一个想要入坑的算法的 ...
最新文章
- 这几天研究了一下JDK14,发现它处理NPE的方式,真香!
- 常考数据结构和算法:跳台阶
- 如何设计通用的网站模板
- Linux账号和权限管理详解(超详细示例操作)!
- Nvidia Jetson TX2+Intel Realsense D435i跑ORB_SLAM3
- 批量添加后缀_掌握这 6 个批量处理技巧,少做 80% 的无用功!
- Pandas读取excel中的数据,并利用现有列数据生成新列
- uniapp实现签名板效果
- 下载XAMPP并安装和使用(Mac环境)
- metasploit中msf批量监测
- 黑莓9900 刷机体验(ROM:7.1.0.318_DoCoMo_Japan版)
- MySQL之Explain
- ios 截屏保存图片
- 产品沉思录精选:拒绝信息成瘾,重新思考你和信息的关系。
- 西电微机系统课程设计——步进电机开环控制系统设计
- python线程isalive_如何在线程类上使用.isAlive()
- 电子邮件营销中的邮件主题设计
- 计算机表格行列知识,计算机基础知识——应用表格.ppt
- Appium学习:雷电模拟器的使用
- linux内核设置mac地址,Linux下如何修改网卡MAC地址
热门文章
- python中html.parser_在Python中使用HTMLParser解析HTML的教程
- html三列布局源码,HTML三列布局 - 黄柳淞的个人页面 - OSCHINA - 中文开源技术交流社区...
- mysql的调试与分析_mysql日志管理分析调试实例_MySQL
- 怎么做图片文字二维码一起_怎么做?才能让文字编排更出彩
- inner join 和 exists 效率_一个in、exists、join的简单测试
- drawable文件怎么添加图片_怎么给PDF文件添加书签
- 2020年高考数学试题难吗?历史上最难数学卷不是2003!
- 大数据时代,数据科学都有些啥?
- 震撼!英伟达用深度学习做图像修复,毫无ps痕迹
- 视觉开发需要什么程度的数学_角度的概念在视觉上非常直观,但其数学定义并不是那么简单...