[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;
}
原文地址:https://www.cnblogs.com/Chtholly/p/11770460.html