【模板·后缀数组/sa】洛谷 P3809 【模板】后缀排序

upd 2019/05/14 :给代码加上了注释

题目:后缀排序
大佬的讲解:后缀数组详解 [自为风月马前卒]
代码:
#include<bits/stdc++.h>
using namespace std;

#define maxn 1000000

int n;
char a[maxn+5];

int m;	//桶的个数 
int sa[maxn+5],rk[maxn+5];	//排名为sa[i]的子串为[sa[i],n],子串[i,n]的排名为rk[i]
int tax[maxn+5],tp[maxn+5];	//基数排序相关
//tax:桶中的元素个数

void readin() {
	scanf("%s",a+1);
	n=strlen(a+1);
}

void rsort() {
	memset(tax,0,sizeof(tax));
	for(int i=1;i<=n;i++) tax[rk[tp[i]]]++;	//塞入桶 
	for(int i=1;i<=m;i++) tax[i]+=tax[i-1];	//前缀和 
	for(int i=n;i>=1;i--) sa[tax[rk[tp[i]]]--]=tp[i];	//倒着从桶中取出,计算sa 
}

void makesa() {
	for(int i=1;i<=n;i++) rk[i]=(int)a[i],tp[i]=i;	//初始化排名 
	rsort();
	for(int k=1;k<=n;k<<=1) {	//排序长度小于等于2^k的后缀 
		int num=0;
		//rk[i]:第一关键字,即当前子串的排名 
		//tp[num]:第二关键字排名为num的字符串编号 
		for(int i=n-k+1;i<=n;i++) tp[++num]=i;	//没有第二关键字的 
		for(int i=1;i<=n;i++) if(sa[i]>k) tp[++num]=sa[i]-k;	//sa[i]为sa[i]-k的第二关键字 
		rsort();
		swap(rk,tp);	//tp变为上一次的rk 
		rk[sa[1]]=1;
		num=1;	//下一次需要桶的个数 
		for(int i=2;i<=n;i++) {
			if(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+k]==tp[sa[i-1]+k]) rk[sa[i]]=num;	//排名相同 
			else rk[sa[i]]=++num;	//排名不同 
		}
		if(num==n) break;	//倍增结束 
		m=num;
	}
}

int main() {
	readin();
	m=122;
	makesa();
	for(int i=1;i<=n;i++) printf("%d ",sa[i]);	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值