# poj3581 Sequence (后缀数组)

 Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6305 Accepted: 1364 Case Time Limit: 2000MS

Description

Given a sequence, {A1A2, ..., An} which is guaranteed AA2, ..., An,  you are to cut it into three sub-sequences and reverse them separately to form a new one which is the smallest possible sequence in alphabet order.

The alphabet order is defined as follows: for two sequence {A1A2, ..., An} and {B1B2, ..., Bn}, we say {A1A2, ..., An} is smaller than {B1B2, ..., Bn} if and only if there exists such i ( 1 ≤ i ≤ n) so that we have Ai < Bi and Aj = Bj for each j < i.

Input

The first line contains n. (n ≤ 200000)

The following n lines contain the sequence.

Output

output n lines which is the smallest possible sequence obtained.

Sample Input

5
10
1
2
3
4


Sample Output

1
10
2
4
3


Hint

{10, 1, 2, 3, 4} -> {10, 1 | 2 | 3, 4} -> {1, 10, 2, 4, 3}

ps:这题不能用多组数据输入，会wa，也是醉了。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
#define lson th<<1
#define rson th<<1|1
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 400050
int sa[maxn],a[maxn],b[maxn],pos[maxn];
int wa[maxn],wb[maxn],wv[maxn],we[maxn];
int rk[maxn],height[maxn];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void build_sa(int *r,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++)we[i]=0;
for(i=0;i<n;i++)we[x[i]=r[i]]++;
for(i=1;i<m;i++)we[i]+=we[i-1];
for(i=n-1;i>=0;i--)sa[--we[x[i]]]=i;
for(j=1,p=1;p<n;j*=2,m=p){
for(p=0,i=n-j;i<n;i++)y[p++]=i;
for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
for(i=0;i<n;i++)wv[i]=x[y[i]];
for(i=0;i<m;i++)we[i]=0;
for(i=0;i<n;i++)we[wv[i]]++;
for(i=1;i<m;i++)we[i]+=we[i-1];
for(i=n-1;i>=0;i--)sa[--we[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}

void calheight(int *r,int n)
{
int i,j,k=0;
for(i=1;i<=n;i++)rk[sa[i]]=i;
for(i=0;i<n;height[rk[i++] ]=k){
for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
}
}

int calmin(int n)
{
int minx=inf,i;
int weizhi=-1;
for(i=2;i<n;i++){
if(rk[i]<minx){
minx=rk[i];
weizhi=i;
}
}
return weizhi;
}
int c[maxn],cnt;
int d[maxn];

int main()
{
int m,i,j,tot,n,weizhi,mm;
scanf("%d",&n);
tot=0;
for(i=0;i<n;i++){
scanf("%d",&a[i]);
pos[++tot]=a[i];
}
sort(pos+1,pos+1+tot);
tot=unique(pos+1,pos+1+tot)-pos-1;

for(i=0;i<n;i++){
a[i]=lower_bound(pos+1,pos+1+tot,a[i])-pos;
b[n-1-i]=a[i];
}
b[n]=0;
build_sa(b,n+1,200010);
calheight(b,n);
weizhi=calmin(n);

cnt=0;
for(i=weizhi;i<n;i++){
c[cnt++]=pos[b[i] ];
}

m=0;
for(i=0;i<weizhi;i++){
d[m++]=b[i];
}
for(i=0;i<m;i++){
d[i+m]=d[i];
}
mm=m*2;

d[mm]=0;
build_sa(d,mm+1,200010 );
calheight(d,mm);

int minx=inf;
weizhi=-1;
for(i=1;i<m;i++){
if(rk[i]<minx){
minx=rk[i];
weizhi=i;
}
}
for(i=weizhi;i<m;i++){
c[cnt++]=pos[d[i] ];
}
for(i=0;i<weizhi;i++){
c[cnt++]=pos[d[i] ];
}

for(i=0;i<cnt;i++){
printf("%d\n",c[i]);
}
}

08-06 598

02-08 307

09-08 120

08-31 215

09-04 5

06-08 2269

06-10 234

10-19 30

04-12 98

01-23 20

09-21 347

02-27 13

04-14 32

09-08 8

09-28 120

02-26 433

03-19 83万+

04-14 62万+

03-13 16万+

03-01 14万+

#### 技术大佬：我去，你写的 switch 语句也太老土了吧

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客