bzoj 4319: Suffix reconstruction 后缀数组+构造

题目大意

给定后缀数组sa,要求构造出满足sa数组的字符串.或输出无解\(n\leq 5*10^5\)

题解

我们按照字典序来考虑每个后缀
对于\(Suffix(sa[i])\)\(Suffix(sa[i-1])\)
我们一定知道\(Suffix(sa[i-1])<Suffix(sa[i])\).
如果我们有\(Suffix(sa[i-1]+1)<Suffix(sa[i]+1)\)
那么\(sa[i]\)\(sa[i-1]\)两个位置上的字符相等时也满足条件
那么从贪心的角度来讲我们就让\(sa[i] = sa[i-1]\)
如果我们有\(Suffix(sa[i-1]+1)>Suffix(sa[i]+1)\)
那么就必须有\(sa[i-1]\)上的字符\(<\) \(sa[i]\)上的字符了
对于这个后缀的大小判断我们直接使用\(rank\)数组即可

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
    x=0;char ch;bool flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 500010;
int sa[maxn],rank[maxn];
char s[maxn];
int main(){
    int n;read(n);
    for(int i=1;i<=n;++i){
        read(sa[i]);
        rank[sa[i]] = i;
    }
    char nw = 'a';
    s[sa[1]] = nw;rank[n+1] = 0;
    for(int i=2;i<=n;++i){
        if(rank[sa[i-1]+1] > rank[sa[i]+1]) ++ nw;
        if(nw > 'z') return puts("-1");
        s[sa[i]] = nw;
    }s[n+1] = '\0';
    printf("%s\n",s+1);
    getchar();getchar();
    return 0;
}
  
posted @ 2017-02-18 20:56 Sky_miner 阅读(...) 评论(...) 编辑 收藏