后缀树组搬运(待补充)

后缀树组经典例题 https://blog.csdn.net/tianyuhang123/article/details/54977648

后缀树讲解 https://blog.csdn.net/YxuanwKeith/article/details/50636898

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

using namespace std;

const int MAXN=1000005;

char str[MAXN];
int SA[MAXN];   //排名为i的后缀的起始位置 
int RANK[MAXN];  //第i个后缀的排名 
int tax[MAXN];  //计数排序辅助数组 
int tp[MAXN];  //rank的辅助数组,第二关键字,意义同SA 
int a[MAXN];  //原串 
int height[MAXN];//LCP
int N,M;   //M为当前排名的种类 

int get_int(char c)
{
	if(c>='A'&&c<='Z') return c-'A';
	return c-'a'+26;
}

void init()
{
	scanf("%s",str);
	N=strlen(str);
	for(int i=0;i<N;i++) a[i+1]=str[i];
}

void Rsort()
{
	for(int i=0; i<=M; i++) tax[i]=0;
	for(int i=1; i<=N; i++) tax[RANK[tp[i]]]++;
	for(int i=1; i<=M; i++) tax[i]+=tax[i-1]; //排最低位(在i前面有多少个) 
	for(int i=N; i>=1; i--) SA[tax[RANK[tp[i]]]--]=tp[i];
}//第二关键字排在i位,其上一轮比较时的排名为rank在这个排名及之后有tax个,那么排名SA为tax的编号就是第二关键字排在tp的,因为第一关键字已经排好了 

int cmp(int *f,int x,int y,int w) {return f[x]== f[y]&& f[x+w]== f[y+w];}  //倍增 

void Suffix()
{
	for(int i=1; i<=N; i++) RANK[i]=a[i], tp[i]=i;
	M=127, Rsort();
	
	for(int w=1, p=1, i; p<N; w+=w, M=p) //w长度,M种不同排名 
	{
		for(p=0, i=N-w+1; i<=N; i++) tp[++p]=i;  //长度过长,超过部分设为0 
		for(i=1; i<=N; i++) if(SA[i]>w) tp[++p]=SA[i]-w;  // 第二关键字排p位的 
		
		Rsort(); swap(RANK,tp); RANK[SA[1]]=p=1;//得到RANK,并把它赋给tp,用于后边 
		
		for(i=2;i<=N;i++) RANK[SA[i]]= cmp(tp,SA[i],SA[i-1],w)? p: ++p;//统计有多少种排名 
	}
	//LCP
	int j,k=0;
	for(int i=1; i<=N; height[RANK[i++]]=k)//相关证明见训练指南 
	for(k=k? k-1: k, j=SA[RANK[i]-1]; a[i+k]== a[j+k]; k++);
}

void out()
{
	for(int i=1;i<=N;i++) printf("%d ",SA[i]);
}

int main()
{
	init(); Suffix(); out();
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/WWWengine/article/details/81325315