[CSP校内集训]rank
题意
给出一个字符串后缀排序之后的数组\(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;
}