题意
给出一个字符串后缀排序之后的数组\(sa_i\),求原字符串(字典序最小),无解输出-1
思路
显然从\(rk_1\)开始填字符是可以保证字符单调不降的
找到\(sa\)值相邻的两个位置,现在需要知道\(rk_i\)和\(rk_{i+1}\)是否可以填相邻字符;当它们填相同字符时需要比较后一位,如果相对关系相同则可行(因为后一位默认已经成立)
举个栗子:\(4,2,3,1\),查看4能不能和3填同一个字符,则判断后一位2和1;而\(4>3 \&\& 2>1\),所以可以相同
Code
#include<bits/stdc++.h> #define N 200005 #define Min(x,y) ((x)<(y)?(x):(y)) #define Max(x,y) ((x)>(y)?(x):(y)) using namespace std; typedef long long ll; int n,a[N],loc[N]; bool sm[N]; char ans[N]; template <class T> void read(T &x) { char c; int sign=1; while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48; while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign; } int main() { freopen("rank.in","r",stdin); freopen("rank.out","w",stdout); read(n); for(int i=1;i<=n;++i) read(a[i]),loc[a[i]]=i; a[n+1]=0;//强调2333 for(int i=1;i<n;++i) sm[i+1]=(a[loc[i]+1]<a[loc[i+1]+1]); char now='a'; ans[loc[1]]=now; for(int i=2;i<=n;++i) { if(!sm[i]) ++now; if(now>'z') {printf("-1");return 0;} ans[loc[i]]=now; } for(int i=1;i<=n;++i) putchar(ans[i]); return 0; }