【模板】SA数组--sa[]与rk[]求解(height[]被我咕掉了)
一. 计数排序优化 O(nlogn)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+2;
int n,m;
char s[N];
int sa[N],rk[N],cnt[200],oldrk[N],oldsa[N];
int main() {
scanf("%s",s+1);
n=strlen(s+1);
m=128;
for(int i=1;i<=n;i++) cnt[rk[i]=s[i]]++;
for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
for(int w=1,q;w<n;w++,m=q) {
int cur=0;
for(int i=n-w+1;i<=n;i++) oldsa[++cur]=i;
for(int i=1;i<=n;i++) {
if(sa[i]>w) oldsa[++cur]=sa[i]-w;
}
memset(cnt,0,sizeof cnt);
for(int i=1;i<=n;i++) cnt[rk[i]]++;
for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=oldsa[i];
q=0;
memcpy(oldrk,rk,sizeof rk);
for(int i=1;i<=n;i++) {
if(oldrk[sa[i]]==oldrk[sa[i-1]] &&
oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) {
rk[sa[i]]=q;
}
else {
rk[sa[i]]=++q;
}
}
if(q==n) break;
}
for(int i=1;i<=n;i++) printf("%d ",sa[i]);
return 0;
}
二. 快排优化 O(n^2 logn)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+2;
int n,w; //lambda 要捕获w, 我们需要将w作为全局变量
char s[N];
int sa[N],rk[N],oldrk[N];
int main() {
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++) sa[i]=i,rk[i]=s[i];
int q;
for(w=1;w<n;w++) {
sort(sa+1,sa+1+n,[](int x,int y){
return (rk[x]==rk[y])?rk[x+w]<rk[y+w]:rk[x]<rk[y];
});
q=0;
memcpy(oldrk,rk,sizeof rk);
for(int i=1;i<=n;i++) {
if(oldrk[sa[i]]==oldrk[sa[i-1]] &&
oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) {
rk[sa[i]]=q;
}
else {
rk[sa[i]]=++q;
}
}
if(q==n) break;
}
for(int i=1;i<=1;i++) printf("%d ",sa[i]);
return 0;
}