[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;
}

猜你喜欢

转载自www.cnblogs.com/Chtholly/p/11770460.html