【bzoj4319】cerc2008 Suffix reconstruction 贪心
题目描述
话说练习后缀数组时,小C 刷遍 poj 后缀数组题,
各类字符串题闻之丧胆。就在准备对敌方武将发出连环杀时,对方一记无中生有,又一招顺手牵羊,小C 程序中的原字符数组就被牵走了。幸运的是,小C 早已经求出了 SA[],为了能东山再起,迅速 A 掉此题,他希望各位忠臣们能帮忙求出一组原字符数组的可行方案。已知原字符数组由小写拉丁字母组成。且小C的SA[]也是有可能求错的, 原数组可能不存在。
输入
输入文件只有一行且为用空格隔开的一个正整数 N。
接下来一行有 N 个数,为 1~N 的排列。
其中对于 100%的数据 N≤500000
输出
一行有 N 个小写拉丁字母,若不存在合法方案输出-1;
样例输入
4
2 3 4 1
样例输出
baab
题解
贪心
首先我们肯定是按照sa的顺序按照字典序从小到大设置字母,且尽量小。
那么我们只需要判断在确定一个新位置时能否放原来的字母。
根据sa的求法,我们比较两个后缀的大小时,如果第一位相同则比较后面的大小,相当于比较下一个后缀的rank。
所以我们可以先根据sa得到rank,比较时直接比较下一位字符串的rank的大小关系,如果新添加的位置的下一位字符串rank比上一个小,则需要增加新字母,否则不需要。
说了这么多还是不如直接看代码直白~
#include <cstdio> #define N 500010 int sa[N] , rank[N]; char str[N]; int main() { int n , i; char ch = 'a'; scanf("%d" , &n); for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &sa[i]) , rank[sa[i]] = i; str[sa[1]] = ch; for(i = 2 ; i <= n ; i ++ ) { if(rank[sa[i] + 1] < rank[sa[i - 1] + 1]) ch ++ ; if(ch > 'z') { printf("-1\n"); return 0; } str[sa[i]] = ch; } printf("%s\n" , str + 1); return 0; }