1. 程式人生 > >BZOJ 4319: cerc2008 Suffix reconstruction(後綴數組)

BZOJ 4319: cerc2008 Suffix reconstruction(後綴數組)

pac printf 字母 接下來 get ret 思路 int 當前

題面

Description
話說練習後綴數組時,小C 刷遍 poj 後綴數組題,
各類字符串題聞之喪膽。就在準備對敵方武將發出連環殺時,對方一記無中生有,又一招順
手牽羊,小C 程序中的原字符數組就被牽走了。幸運的是,小C 早已經求出了 SA[],為了
能東山再起,迅速 A 掉此題,他希望各位忠臣們能幫忙求出一組原字符數組的可行方案。已
知原字符數組由小寫拉丁字母組成。且小C的SA[]也是有可能求錯的, 原數組可能不存在。

Input
輸入文件只有一行且為用空格隔開的一個正整數 N。
接下來一行有 N 個數,為 1~N 的排列。
其中對於 100%的數據 N≤500000

Output
一行有 N 個小寫拉丁字母,若不存在合法方案輸出-1;

Sample Input
4

2 3 4 1
Sample Output
dabc

解題思路

  很有意思的一道題,自己動手模擬幾個大概就能發現規律了。就是如果當前\(sa\)的後綴的位置如果大於下個\(sa\)後綴的位置,那麽下一個的字典序一定比這個大,否則可以相等,所以\(O(n)\)掃一遍即可。

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>

using namespace std;
const int MAXN = 500005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) f=ch==‘-‘?0:1,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar();
    return f?x:-x;
}

int sa[MAXN],nxt[MAXN],pos[MAXN];
int num,ans[MAXN],n;

int main(){
    n=rd();
    for(int i=1;i<=n;i++) sa[i]=rd(),pos[sa[i]]=i;pos[n+1]=0;
    ans[sa[1]]=1;num=1;
    for(int i=1;i<n;i++){
        if(pos[sa[i]+1]<pos[sa[i+1]+1]) ans[sa[i+1]]=num;
        else ans[sa[i+1]]=++num;
        if(num>26) break;
    }
    if(num>26) puts("-1");
    else for(int i=1;i<=n;i++) printf("%c",char(ans[i]+‘a‘-1));
    return 0;
}

BZOJ 4319: cerc2008 Suffix reconstruction(後綴數組)