字符串-后缀数组-倍增

文章目录

学习文献

1.https://www.cnblogs.com/jinkun113/p/4743694.html
2.https://www.cnblogs.com/zwfymqz/p/8413523.html
3.https://xminh.github.io/2018/02/27/后缀数组-最详细(maybe)讲解.html
4.https://www.cnblogs.com/victorique/p/8480093.html
5.https://blog.csdn.net/qq_37774171/article/details/81776029

代码

/**********************
User:Mandy.H.Y
Language:c++
Problem:luogu3809 Suffix Sorting
Algorithm:Suffix Array
Date:2019.7.19
Scores:
**********************/
//指针是程序员的杀手
//怕了怕了 
//x:一开始是原始数据r的拷贝
//(其实也表示长度为1的字符串的排名),之后表示k/2长度字符串的排名.
//y:指示长度为k 的字符串的第二关键字的排序结果
//通过存储k长字符串的第一关键字的下标进行指示.
#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e6 + 5;

int n;
int w[155],a[maxn],sa[maxn],a1[maxn];
char c[maxn];
int x[maxn],y[maxn];

void file(){
	freopen("3809.in","r",stdin);
	freopen("3809.out","w",stdout);
}

void readdata(){
	scanf("%s",c);
	n = strlen(c);
	for(int i = 0;i < n; ++ i)
		a[i] = c[i] - '0' + 1;
}

void get_SA(int m){
	
//	int *x = a,*y = a1;
	
	for(int i = 0;i < m; ++ i) w[i] = 0;
	for(int i = 0;i < n; ++ i) ++ w[x[i] = a[i]];
	for(int i = 1;i < m; ++ i) w[i] += w[i - 1];
	for(int i = n - 1;i >= 0; -- i) sa[ -- w[x[i]]] = i;
	//倒序保证在字母相同的情况下编号小的在前面 
	
	for(int k = 1;k <= n;k <<= 1){
		
		int p = 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) w[i] = 0;
		for(int i = 0;i < n; ++ i) ++ w[x[y[i]]];
		for(int i = 1;i < m; ++ i) w[i] += w[i - 1];
		for(int i = n - 1;i >= 0; -- i) sa[ -- w[x[y[i]]]] = y[i];
		
		swap(x,y);x[sa[0]] = 0;
		p = 1;//初始化
		for(int i = 1;i < n; ++ i){
			x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p - 1 : p ++;
		}
		
		if(p >= n) break;
		m = p;
		
	}
}

int rank[maxn],height[maxn];

void  get_height(){
	for(int i = 0;i < n; ++ i) rank[sa[i]] = i;
	int  k = 0;
	for(int i = 0;i < n; ++ i){
		if(k) -- k;
		if(rank[i] == 0) continue; 
		//第一名height为0 
		int j = sa[rank[i] - 1];//排名在i的前一个的编号 
		while(a[i + k] == a[j + k]) ++k;
		//标号从零开始,k为个数
		height[rank[i]] = k; //height[rank[i]]
	}
}

void work(){
	get_SA(150); 
//	get_height();
	for(int i = 0;i < n; ++ i) printf("%d ",sa[i] + 1);
	
}

int main(){
//	file();
//	freopen("testdata.in","r",stdin);
	readdata();
	work();
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值