您的位置:首页 > 其它

P3809 【模板】后缀排序

2017-07-31 17:33 267 查看

P3809 【模板】后缀排序

题目背景

这是一道模板题。

题目描述

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

输入输出格式

输入格式:

 

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
ababa
输出样例#1:
5 3 1 4 2

说明

n <= 10^6n<=10​6​​

code

本题代码

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 1000100;

char s
;
int sa
,t1
,t2
,c
,rnk
,height
;
//sa[i]  排名为i的是谁 -下标
//rnk[i] i的排名 -名次
//height[i]  排名为i的后缀与排名为i-1的后缀的最长公共前缀长度
int n,m = 130;

void get_sa() {
int *x = t1,*y = t2;
//基数排序
for (int i=0; i<m; ++i) c[i] = 0;
for (int i=0; i<n; ++i) c[x[i] = s[i]]++;
for (int i=1; i<m; ++i) c[i] += c[i-1];
for (int i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
/*
每次循环
都将两个长度k子串合并为一个长度为2k的串
其中前k个字符构成的子串的排名为第一关键字,后k个字符为第二关键字
并求出合并后的字符串的排名
*/
//每次排名得到一共有多少个排名p,由p优化m的值,节省空间。
for (int k=1; k<=n; k<<=1) {
int p = 0;
/*
y数组是第二关键字排序的结果,
存储的是2k长度的字符串的第一关键字的下标
*/
/*
n-k到n-1中所有的元素第二关键字为0
*/
for (int i=n-k; i<n; ++i) y[p++] = i;
for (int i=0; i<n; ++i) if (sa[i] >= k) y[p++] = sa[i] - k;
for (int i=0; i<m; ++i) c[i] = 0;
for (int i=0; i<n; ++i) c[x[y[i]]]++;
for (int i=1; i<m; ++i) c[i] += c[i-1];
for (int i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = 1;
x[sa[0]] = 0;
for (int i=1; i<n; ++i)
x[sa[i]] = (y[sa[i-1]]==y[sa[i]] && sa[i-1]+k<n && sa[i]+k<n &&
y[sa[i-1]+k]==y[sa[i]+k]) ? p-1 : p++;
if (p >= n) break;
m = p;
}
}
void get_height() {
for (int i=0; i<n; ++i) rnk[sa[i]] = i; // sa排名为i的下标,rnk[i]下标为i的后缀的名次。
int k = 0;
height[0] = 0;
/*
性质:height[rnk[i]] >= height[rnk[i-1]]-1
理解为起始下标为i的后缀和i-1的后缀除了开头第一个字符不同,其余的相同的
即suffix[i,n]与suffix[i-1,n]只有第一个字符不同。
所以suffix[i-1,n]匹配上的子串,与suffix[i,n]匹配的子串,中k-1个是相等的。
*/
for (int i=0; i<n; ++i) {
if (!rnk[i]) continue;
if (k) k--;
int j = sa[rnk[i]-1]; // 前一个排名的后缀的开始位置
while (i+k<n && j+k<n && s[i+k]==s[j+k]) k++;
height[rnk[i]] = k;
}
}
int main() {
scanf("%s",s);
n = strlen(s);
get_sa();
for (int i=0; i<n; ++i)
printf("%d ",sa[i]+1);
return 0;
}
View Code

 

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: