后缀数组模板 UOJ#35. 后缀排序

从梓轩学姐提交记录那里搞来的,简单易懂,没有那些奇奇怪怪的东西...

#include<cstdio>
#include<cstring>
const int MAXN=100000,D=50;
int n,str[MAXN+D];
int sa[MAXN+D],rank[MAXN+D],height[MAXN+D];
int p[MAXN+D],temp[MAXN+D],cnt[MAXN+D];
inline bool equ(int x,int y,int l){return rank[x]==rank[y]&&rank[x+l]==rank[y+l];}
void init(){
	char ch=getchar();
	while(ch>='a'&&ch<='z')str[n++]=ch-'a',ch=getchar();
}
void doubling()
{
	str[n]=rank[n]=-1;
	for(int i=0;i<n;i++)sa[i]=i,rank[i]=str[i];
	for(int i,l=0,pos=0,sig=26;pos<n-1;sig=pos)
	{
		for(i=n-l,pos=0;i<n;i++)p[pos++]=i;
		for(i=0;i<n;i++)if(sa[i]>=l)p[pos++]=sa[i]-l;
		memset(cnt,0,sizeof cnt);
		for(i=0;i<n;i++)cnt[rank[p[i]]]++;
		for(i=1;i<=sig;i++)cnt[i]+=cnt[i-1];
		for(i=n-1;i>=0;i--)sa[--cnt[rank[p[i]]]]=p[i];
		for(temp[sa[0]]=pos=0,i=1;i<n;i++)
		{
			if(!equ(sa[i],sa[i-1],l))pos++;
			temp[sa[i]]=pos;
		}
		for(i=0;i<n;i++)rank[i]=temp[i];
		if(!l)l=1;else l<<=1;
	}
}
void pre()
{
	int i,k;
	for(i=k=0;i<n;i++)
	{
		if(k)k--;
		if(rank[i]==0)continue;
		for(int j=sa[rank[i]-1];str[i+k]==str[j+k];)
			k++;
		height[rank[i]]=k;
	}
}
void print()
{
	for(int i=0;i<n;i++)
		printf("%d ",sa[i]+1);
	printf("\n");
	for(int i=1;i<n;i++)
		printf("%d ",height[i]);
}
int main(){
	init();
	if(n==1){printf("1");return 0;}
	doubling();
	pre();
	print();
	return 0;
}

  

posted @ 2018-02-28 07:58  mybing  阅读(142)  评论(0编辑  收藏  举报