【Luogu】P3809后缀排序(后缀数组模板)
今天终于学会了后缀数组模板qwq
不过只会模板emmmm
首先我们有一本蓝书emmmmmm
然后看到蓝书221页代码之后我就看不懂了
于是请出rqy
rqy:
一开始那是个对单个字符排序的操作啊
c[i]表示值为i的字符有多少个
x[i]表示第i个位置的优先级是多少
sa[i]表示优先级是i的字符位置
然后第一行明显是初始化,第二行明显就是统计字符个数
至于第三行为什么要求前缀和呢
我们思考优先级越小的排的越靠前
所以说,设优先级是0的有c[0]个,优先级是1的有c[1]个,以此类推
所以说我们有c[0]个字符假设是'0',应该排到[ 0,c[0] )区间左闭右开
然后截下来有c[1]个字符假设是'1',应该排到[ c[0],c[0]+c[1] )区间左闭右开
然后以此类推
所以我们简记一下c的前缀和,记为S
于是我们排序的区间就变成了[0,S[0]) [S[0],S[1]) [S[1],S[2])
等等等等。
然后就可以愉快的基数排序啦
然后考虑我们怎么搞两个关键字的排序
就是我先把第二关键字排上,然后保证排序算法稳定的情况下排第一关键字
第二关键字我可以直接枚举排。第一关键字……基数排序可以搞定qwq。
然后看相邻的两个后缀编号是否相等,如果相等说明没能把它们区分开,接着排,如果不相等就可以退出了。
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cstdlib>
#define maxn 2000100
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} char s[maxn];
int sa[maxn];
int x[maxn];
int y[maxn];
int c[maxn];
int len; void build(int m){
for(int i=;i<=m;++i) c[i]=;
for(int i=;i<=len;++i) c[x[i]=s[i]]++;
for(int i=;i<=m;++i) c[i]+=c[i-];
for(int i=len;i>=;--i) sa[c[x[i]]--]=i;
for(int k=;k<=len;k<<=){
int p=;
for(int i=len-k+;i<=len;++i) y[++p]=i;
for(int i=;i<=len;++i)
if(sa[i]>k) y[++p]=sa[i]-k;
for(int i=;i<=m;++i) c[i]=;
for(int i=;i<=len;++i) c[x[y[i]]]++;
for(int i=;i<=m;++i) c[i]+=c[i-];
for(int i=len;i>=;--i) sa[c[x[y[i]]]--]=y[i];
std::swap(x,y);
p=; x[sa[]]=;
for(int i=;i<=len;++i)
x[sa[i]]=y[sa[i-]]==y[sa[i]]&&y[sa[i-]+k]==y[sa[i]+k]?p:++p;
if(p>=len) break;
m=p;
}
} int main(){
scanf("%s",s+);
len=strlen(s+);
build();
for(int i=;i<=len;++i) printf("%d ",sa[i]);
return ;
}
【Luogu】P3809后缀排序(后缀数组模板)的更多相关文章
- UOJ #35. 后缀排序[后缀数组详细整理]
#35. 后缀排序 统计 描述 提交 自定义测试 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符 ...
- Uoj #35. 后缀排序(后缀数组)
35. 后缀排序 统计 描述 提交 自定义测试 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在 ...
- Codevs 1500 后缀排序(后缀数组)
1500 后缀排序 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个 ...
- Luogu P3809 【模板】后缀排序(后缀数组板题)
忘完了- emmm-
- UOJ #35. 后缀排序 后缀数组 模板
http://uoj.ac/problem/35 模板题,重新理了一遍关系.看注释吧.充分理解了倍增的意义,翻倍之后对上一次排序的利用是通过一种类似于队列的方式完成的. #include<ios ...
- 【UOJ #35】后缀排序 后缀数组模板
http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...
- UOJ.35.[模板]后缀排序(后缀数组 倍增)
题目链接 论找到一个好的教程的正确性.. 后缀数组 下标从1编号: //299ms 2560kb #include <cstdio> #include <cstring> #i ...
- 洛谷.3809.[模板]后缀排序(后缀数组 倍增) & 学习笔记
题目链接 //输出ht见UOJ.35 #include<cstdio> #include<cstring> #include<algorithm> const in ...
- [UOJ#35] [UOJ后缀数组模板题] 后缀排序 [后缀数组模板]
后缀数组,解决字符串问题的有利工具,本题代码为倍增SA算法 具体解释详见2009年国家集训队论文 #include <iostream> #include <algorithm> ...
- luogu3809 后缀排序 后缀数组
ref and 挑战程序设计竞赛. 主要是发现自己以前写得代码太难看而且忘光了,而且我字符串死活学不会啊,kmp这种东西我都觉得是省选+难度啊QAQ #include <iostream> ...
随机推荐
- phar打包项目压力对比测试
工具 http_load 测试url: http://api.test.chaoma.me/agent/ad/good_goods/query http://api.test.chaoma.me/ag ...
- 【Orange Pi Lite2】 ——1《如何开始使用开源硬件》
[Orange Pi Lite2] --1<如何开始使用开源硬件> 本文只在博客园发布 在开始前你需要准备的材料与软件 用户手册_Orange Pi Lite2 OrangePi_Lite ...
- Android内核剖析(1)
Linux的启动过程 开机上电执行bootloader,将内核的前n条指令加载到系统内存中------>系统内核的初始化----------->启动应用程序. bootloader的位置装 ...
- AWVS12 防止反复注册
以管理员权限运行cmd,输入以下内容: cacls "C:\ProgramData\Acunetix\shared\license." /t /p everyone:r 如图:
- hd - MFM/IDE 硬盘设备
描述 DESCRIPTION hd* 开头的设备是以裸模式(raw mode)访问MFM/IDE类型硬盘的块设备. 第一个IDE驱动控制器上的主盘(主设备号3)是 hda ;从盘是 hdb. 第二个I ...
- guruguru
6576: guruguru 时间限制: 1 Sec 内存限制: 128 MB提交: 28 解决: 12[提交] [状态] [讨论版] [命题人:admin] 题目描述 Snuke is buyi ...
- 关于tomcat的classloader的一点想法
关于tomcat的classloader相关的帖子网上非常多,我觉得比较好的有: https://www.jianshu.com/p/d90e4430b0b9 https://blog.csdn.ne ...
- 数据库-SQL语法:把一个字段的值设为随机整数
update test2 set zuig = (cast ( ceiling (rand()*9) as int))
- Vue 后台管理
这里是结合vue和element快速成型的一个demo 里面展示了基本的后台管理界面的大体结构和element的基本操作 GitHub的地址:https://github.com/wwwming/ad ...
- PAT (Basic Level) Practise (中文)- 1008. 数组元素循环右移问题 (20)
一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0A1……AN-1)变换为(AN-M …… AN-1 A0 ...