题面
https://www.luogu.org/problem/P3809
题解
好像写的时候还不理解,但是现在理解了。
排序是间接排序:对于每个点对它的位置$+1$,表示这个位置具有的点的个数,再求前缀和,最后一个一个减回去,得到排名。
对于双关键字的情况,排两次序,先第二再第一。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define N 1000050 #define ri register int using namespace std; char s[N]; int n,m; int sa[N],rank[N],tp[N],tax[N]; void cntsort(){ for (ri i=0;i<=m;i++) tax[i]=0; for (ri i=1;i<=n;i++) tax[rank[i]]++; for (ri i=1;i<=m;i++) tax[i]+=tax[i-1]; for (ri i=n;i>=1;i--) sa[tax[rank[tp[i]]]--]=tp[i]; /**/ } void Suffixsort(){ m=75; for (ri i=1;i<=n;i++) rank[i]=s[i]-'0'+1,tp[i]=i; /**/ cntsort(); for (ri w=1,p=0;p<n;m=p,w<<=1) { p=0; for (ri i=1;i<=w;i++) tp[++p]=n-w+i; for (ri i=1;i<=n;i++) if (sa[i]>w) tp[++p]=sa[i]-w; cntsort(); swap(tp,rank); // tp rank not tp sa rank[sa[1]]=p=1; // low for (ri i=2;i<=n;i++) { // 2 rank[sa[i]]=(tp[sa[i-1]]==tp[sa[i]] && tp[sa[i-1]+w]==tp[sa[i]+w]) ? p : ++p; } } } int main(){ scanf("%s",s+1); n=strlen(s+1); Suffixsort(); //cout<<n<<endl; for (ri i=1;i<=n;i++) printf("%d ",sa[i]); }