2020牛客暑期多校训练营(第一场)A B-Suffix Array
题目链接:https://ac.nowcoder.com/acm/contest/5666/A
题意:给定一个由a和b组成的字符串,定义b数组为
把字符串的每一个后缀转化为b数组进行字典序排序,输出最后的排序结果
关于这题的题解是一个后缀数组的结论
只适用于两种字符的情况,刚好满足题意。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e5+100;
const ll mod=1e9+7;
int n,m,k,t;
char s[maxn];
int c[maxn],sa[maxn],rk[maxn],tmp[maxn];
int cmp(int x,int y){
if(rk[x]!=rk[y])return rk[x]<rk[y];
else{
int rx,ry;
if(x+k<=n)rx=rk[x+k];
else rx=-1;
if(y+k<=n)ry=rk[y+k];
else ry=-1;
return rx<ry;
}
}
void getsa(int sa[]){
rk[n]=-1;
sa[n]=n;
for(int i=0;i<n;i++){
sa[i]=i;
rk[i]=c[i];
}
for(k=1;k<=n;k*=2){
sort(sa,sa+n+1,cmp);
tmp[sa[0]]=0;
for(int i=1;i<=n;i++){
if(cmp(sa[i-1],sa[i]))
tmp[sa[i]]=tmp[sa[i-1]]+1;
else
tmp[sa[i]]=tmp[sa[i-1]];
}
for(int i=0;i<=n;i++)
rk[i]=tmp[i];
}
}
int main(){
while(~scanf("%d",&n)){
scanf("%s",s);
int a=n,b=n;
for(int i=n-1;i>=0;i--){
if(s[i]=='a'){
if(a==n)c[i]=(n-a)%n;
else c[i]=(n-a+i)%n;
a=i;
}
else{
if(b==n)c[i]=(n-b)%n;
else c[i]=(n-b+i)%n;
b=i;
}
}
getsa(sa);
for(int i=1;i<n;i++)printf("%d ",sa[i]+1);
printf("%d\n",sa[n]+1);
}
}