【模板】后缀排序

题目背景

这是一道模板题。

题目描述

读入一个长度为 \(n\) 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 \(1\) 到 \(n\) 。

输入输出格式

输入格式:

一行一个长度为 \(n\) 的仅包含大小写英文字母或数字的字符串。

输出格式:

一行,共 \(n\) 个整数,表示答案。

输入输出样例

输入样例#1: 复制

ababa

输出样例#1: 复制

5 3 1 4 2

说明

\(n <= 10^6\)


一点点理解?

怎么说呢?

后缀数组是用来处理字符串后缀的有效手段。

虽然 DC3 的时间复杂度比 倍增 要少了一个log。

但是我们在平常中还是用倍增更多一些。

倍增是用基数排序来维护的。

事先说明。我学的后缀数组资源来源与自为风月马前卒大佬的博客(强烈推荐)。

rak[i]=表示后缀开头位置为 i 的排名,也是第一关键词

num[i]=桶计数

tp[i]=第二关键词,也就是基数排序的后半段

sa[i]=第i个排名的后缀的开头位置



先来看个图





接下来看代码

void Sort()
{
for(int i=0;i<=m;i++)num[i]=0;
for(int i=1;i<=n;i++)num[rak[i]]++;
for(int i=1;i<=m;i++)num[i]+=num[i-1];
for(int i=n;i>=1;i--)sa[num[rak[tp[i]]]--]=tp[i];
}

这时候比较难理解的就是最后一句对吧,别急,看后面的代码。

	cnt=0;
for(int i=1;i<=w;i++)tp[++cnt]=n-w+i;
for(int i=1;i<=n;i++)if(sa[i]>w)tp[++cnt]=sa[i]-w;

这是第一次倍增时的确定tp[]值的代码。

为什么先把后面的tp[]值赋为后面小于w(w为当前排序的长度)呢?

因为后面的长度小于等于w的字符串,再怎么倍增第二关键词都是空集,就相当于只比第一关键词。

第二句话,如果sa[i]的位置能在倍增时作为前面第一关键词的第二关键词,那么便让当前第二关键词的位置等于第一关键词。

因为这里sa[i]已经排序好了,所以其实我们是已经求好了第二关键词的大小的,这样就只要回到第一关键词的大小比较即可。

此时sa[num[rak[tp[i]]--]=tp[i] 事实上就是在排好了第二关键词的情况下,求出来的第一关键词的sa[]值。不过这一次的sa[]值已经是第一关键词和第二关键词的总和的字符串的位置。


代码

	#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000100;
char s[N];
int sa[N],rak[N],tp[N],num[N];
int n,m=200;
void Sort(){
for(int i=0;i<=m;i++)num[i]=0;
for(int i=1;i<=n;i++)num[rak[i]]++;
for(int i=1;i<=m;i++)num[i]+=num[i-1];
for(int i=n;i>=1;i--)sa[num[rak[tp[i]]]--]=tp[i];
} void SA_sort(){
for(int i=1;i<=n;i++){
rak[i]=s[i]-'0',tp[i]=i;
}
Sort();
int p=0,w=1,cnt;
while(p<n){
cnt=0;
for(int i=1;i<=w;i++)tp[++cnt]=n-w+i;
for(int i=1;i<=n;i++)if(sa[i]>w)tp[++cnt]=sa[i]-w;
Sort();swap(rak,tp);
rak[sa[1]]=p=1;
for(int i=2;i<=n;i++)
if((tp[sa[i]]==tp[sa[i-1]])&&(tp[sa[i]+w]==tp[sa[i-1]+w]))
rak[sa[i]]=p;
else rak[sa[i]]=++p;
w<<=1;m=p;
}
} int main(){
scanf("%s",s+1);
n=strlen(s+1);
SA_sort();
for(int i=1;i<=n;i++)
{
printf("%d ",sa[i]);
}
return 0;
}

【模板】后缀排序(SA数组)的更多相关文章

  1. UOJ.35.[模板]后缀排序(后缀数组 倍增)

    题目链接 论找到一个好的教程的正确性.. 后缀数组 下标从1编号: //299ms 2560kb #include <cstdio> #include <cstring> #i ...

  2. 洛谷.3809.[模板]后缀排序(后缀数组 倍增) & 学习笔记

    题目链接 //输出ht见UOJ.35 #include<cstdio> #include<cstring> #include<algorithm> const in ...

  3. [luogu] P3809 【模板】后缀排序 (SA)

    板子,照着题解打的倍增版. #include <iostream> #include <cstdio> #include <cstring> using names ...

  4. Java后缀数组-求sa数组

    后缀数组的一些基本概念请自行百度,简单来说后缀数组就是一个字符串所有后缀大小排序后的一个集合,然后我们根据后缀数组的一些性质就可以实现各种需求. public class MySuffixArrayT ...

  5. 洛谷:P3809 【模板】后缀排序(后缀数组模板)

    P3809 [模板]后缀排序 题目链接:https://www.luogu.org/problemnew/show/P3809 题目背景 这是一道模板题. 题目描述 读入一个长度为 nn 的由大小写英 ...

  6. [UOJ#35] [UOJ后缀数组模板题] 后缀排序 [后缀数组模板]

    后缀数组,解决字符串问题的有利工具,本题代码为倍增SA算法 具体解释详见2009年国家集训队论文 #include <iostream> #include <algorithm> ...

  7. P3809 【模板】后缀排序

    P3809 [模板]后缀排序 从这学的 后缀数组sa[i]就表示排名为i的后缀的起始位置 x[i]是第i个元素的第一关键字 y[i]表示第二关键字排名为i的数,在第一关键字中的位置 #include& ...

  8. 2018.11.24 loj#111. 后缀排序(后缀数组)

    传送门 后缀排序模板题. 终于会后缀数组了(然而只会倍增并不会DC3DC3DC3). 在这里列举几个数组的意思: sai:sa_i:sai​:当前排名第iii的后缀的起始下标. rkirk_irki​ ...

  9. [洛谷P3809]【模板】后缀排序

    [洛谷P3809][模板]后缀排序 题目大意: 对于给定的长度为\(n(n\le10^6)\)的字符串求后缀数组\(sa[i]\). 思路: 倍增+快排构造后缀数组.代码参考<挑战程序设计竞赛& ...

随机推荐

  1. 【英雄会】微软题目:几个bing

    今天是元旦,开篇先祝福大家在新的一年心想事成,工作顺利,开心生活每一天 . 看到[英雄会]上出现了微软出的题目:几个bing,题目内容如下: 本届大赛由微软必应词典冠名,必应词典(Bing Dicti ...

  2. jquery 几种类选择器方式

    代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestClas ...

  3. 用Maven创建第一个web项目Struts2项目

    一.创建一个web项目 参考前面文章,项目名:maven-struts-demo. 二.配置pom.xml文件添加struts2依赖 <project xmlns="http://ma ...

  4. SpringCloud学习笔记(13)----Spring Cloud Netflix之Hystrix断路器的隔离策略

    说明 : 1.Hystrix通过舱壁模式来隔离限制依赖的并发量和阻塞扩散 2. Hystrix提供了两种隔离策略:线程池(THREAD)和信号量隔离SEMAPHORE). 1. 线程池隔离(默认策略模 ...

  5. 路飞学城Python-Day17

    [1.编程范式] 1.面向过程编程 2.面向对象编程 [2.面向过程编程] 面向过程:核心就是过程   什么是过程? 过程指的是解决问题的步骤,先做什么,在作什么,面向过程就像是设计一个流水线,是一种 ...

  6. BZOJ 2287 【POJ Challenge】消失之物(DP+容斥)

    2287: [POJ Challenge]消失之物 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 986  Solved: 572[Submit][S ...

  7. BZOJ 2565 最长双回文串(manacher)

    565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3343  Solved: 1692[Submit][Status][Discu ...

  8. redis搭建与安装

    redis提供五种数据类型:string,hash,list,set及zset(sorted set). 第一部分:安装redis 希望将redis安装到此目录 1 /usr/local/redis ...

  9. Ubuntu 16.04 Chrome浏览器安装flash player插件

    1:官网下载插件  flash palyer lash_player_npapi_linux_debug.x86_64.tar.gz 2:解压 提取 libpepflashplayer.so 3:手动 ...

  10. Zabbix分布式配置

    Zabbix是一个分布式监控系统,它可以以一个中心点.多个分节点的模式运行,使用Proxy能大大的降低Zabbix Server的压力,Zabbix Proxy可以运行在独立的服务器上,安装Zabbi ...