萌新求调SA
查看原帖
萌新求调SA
203008
山田リョウ楼主2022/5/1 18:07
// Problem: P1368 【模板】最小表示法
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1368
// Memory Limit: 250 MB
// Time Limit: 1000 ms

#include<stdio.h>
#include<algorithm>
#include<string.h>
int s[600001],sa[600001],oldrk[1200001],rk[600001],cnt[600001],t[600001],t2[600001],p,n,m;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",s+i),s[n+i]=s[i];
	n<<=1;
	for(int i=1;i<=n;++i)sa[i]=i;
	std::sort(sa+1,sa+n+1,[](int x,int y){return s[x]<s[y];});
	p=0;
	for(int i=1;i<=n;++i)rk[sa[i]]=(s[sa[i]]==s[sa[i-1]])?p:++p;
	for(int l=1;(m=p)<n;l<<=1){
		for(int i=1;i<=n;++i)oldrk[i]=rk[i];
		for(int i=1;i<=l;++i)t[i]=n-i+1;
		p=l;
		for(int i=1;i<=n;++i)if(sa[i]>l)t[++p]=sa[i]-l;
		for(int i=1;i<=n;++i)++cnt[t2[i]=oldrk[t[i]]];
		for(int i=1;i<=m;++i)cnt[i]+=cnt[i-1];
		for(int i=n;i;--i)sa[cnt[t2[i]]--]=t[i];
		p=0;
		for(int i=1;i<=n;++i)rk[sa[i]]=(oldrk[sa[i]]==oldrk[sa[i-1]]&&oldrk[sa[i]+l]==oldrk[sa[i-1]+l])?p:++p;
		for(int i=1;i<=m;++i)cnt[i]=0;
	}
	for(int i=0;i<(n>>1);++i)printf("%d ",s[sa[1]-(n>>1)+i]);
	return 0;
}
2022/5/1 18:07
加载中...