基数排序因为每次只有我们所谓的“第一关键字”和“第二关键字”,所以是一次排序复杂度为O(2n),对len进行倍增,所以只要进行log n次排序。所以总复杂度:O(n log n)。
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m;
int rk[N],rk2[N],sum[N],tp[N],sa[N];
char s[N];
inline void qsort()
{
for (register int i=0; i<=m; ++i) sum[i]=0;
for (register int i=1; i<=n; ++i) sum[rk[i]]++;
for (register int i=1; i<=m; ++i) sum[i]+=sum[i-1];
for (register int i=n; i>=1; --i) sa[sum[rk[tp[i]]]]=tp[i],sum[rk[tp[i]]]--;
}
inline void SA()
{
m=75;
for (register int i=1; i<=n; ++i) rk[i]=s[i]-'0'+1,tp[i]=i;
qsort();
int p=0;
for (register int len=1; p<n; m=p,len<<=1)
{
p=0;
for (register int i=n-len+1; i<=n; ++i) tp[++p]=i;
for (register int i=1; i<=n; ++i) if (sa[i]>len) tp[++p]=sa[i]-len;
qsort();
memcpy(rk2,rk,sizeof(rk2));
p=1; rk[sa[1]]=p;
for (register int i=2; i<=n; ++i)
{
if (rk2[sa[i]]==rk2[sa[i-1]] && rk2[sa[i]+len]==rk2[sa[i-1]+len]) p=p; else p++;
rk[sa[i]]=p;
}
}
for (register int i=1; i<=n; ++i) printf("%d ",sa[i]);
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
SA();
return 0;
}