DA后缀数组构造的思想主要的就是倍增
即类似RMQ的双关键字排序
所以就可以用双关键字排序的方法来构造后缀数组
基数排序和快排都可以,鉴于是1e5,直接nlogn就够了
码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 500005
int rk[N],len,n,i,k,cnt;
char str[N];
struct SA
{
int x,y,id;
}sa[N];
bool cmp(SA a,SA b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
void Da2()
{
for(i=0;i<n;i++)sa[i].x=str[i],sa[i].id=i;
for(k=1;k<n;k*=2)
{
for(i=0;i<n;i++)sa[i].y=sa[i+k].x;//得到第二关键字
sort(sa,sa+n,cmp);//排序
cnt=0;
for(i=0;i<n;i++)
{
if(sa[i].x==sa[i-1].x&&sa[i].y==sa[i-1].y);
else cnt++;
rk[sa[i].id]=cnt;
}
for(i=0;i<n;i++)sa[i].x=rk[i],sa[i].id=i;
}
}
int main()
{
scanf("%s",str);
len=strlen(str);
for(i=len;i<len*2-1;i++)
str[i]=str[i-len];
n=len*2-1;
Da2();
sort(sa,sa+n,cmp);
for(i=0;i<n;i++)
{
if(sa[i].id<len)printf("%c",str[sa[i].id+len-1]);
}
}