说在前面
默默地水一道题 练shua练shua手bang
题目
题目大意
给出一个sa[]数组(sa[i] = k表示排第i的后缀是以位置k开始的后缀),请构造出符合条件的原串(只能出现小写英文字母),不存在则输出-1
输入输出格式
输入格式:
第一行一个整数N表示长度(不超过500000)
接下来一行N个整数为sa数组
输出格式:
如果有符合条件的原串,则输出该串
不然输出-1
解法
首先如果字符集足够大,那么一定可以构造出来(sa[1] = 1,sa[2] = 2… sa[N] = N)
现在字符集有了限制,也就是要让字母尽量的小。毫无疑问的ans[sa[1]]=a。现在考虑ans[sa[2]],如果可以的话,肯定让ans[ sa[1] ]和ans[ sa[2] ]相等,很容易发现只要suffix[ sa[1]+1 ]的排名小于suffix[ sa[2]+1 ],就可以相等。
现在就是要求rank数组,由定义rank[ sa[i] ] = i。成功解决此题=w=
下面是自带大常数的代码
/**************************************************************
Problem: 4319
User: Izumihanako
Language: C++
Result: Accepted
Time:660 ms
Memory:5216 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
char ans[500005] ;
int N , sa[500005] , rk[500005] ;
void GG(){
puts( "-1" ) ;
exit( 0 ) ;
}
int main(){
scanf( "%d" , &N ) ;
for( int i = 1 ; i <= N ; i ++ ){
scanf( "%d" , &sa[i] ) ;
rk[ sa[i] ] = i ;
}
int delta = 0 ;
ans[ sa[1] ] = 'a' ;
for( int i = 2 ; i <= N ; i ++ ){
if( rk[ sa[i-1]+1 ] > rk[ sa[i]+1 ] )
delta ++ ;
if( delta == 27 ) GG() ;
ans[ sa[i] ] = 'a' + delta ;
}
ans[ N+1 ] = '\0' ;
puts( ans + 1 ) ;
}