您的位置:首页 > 产品设计 > UI/UE

POJ 3581 Sequence [后缀数组]

2017-02-06 14:32 363 查看
Sequence

Time Limit: 5000MSMemory Limit: 65536K
Total Submissions: 6911Accepted: 1543
Case Time Limit: 2000MS
Description

Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., 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 {A1, A2, ..., An} and {B1, B2, ..., Bn}, we say {A1, A2, ..., An} is smaller than {B1, B2, ..., 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}
Source

POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu
题意:

给出一个字符串,要求将其切成3段,然后将每段翻转,使得得到的新串字典序最小
保证原串第一个字符的字典序比后面的都大

字符串反转后求最小后缀就是第一段啦
后两段的话,保持反转不变,然后复制一份接在后面求最小后缀就行了,自己画图看看吧
注意判断位置的合法性,比如需要分成三份,以及第二次不能分在复制的那一份上

还有,需要离散化........

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2e5+5,INF=1e9;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
return x*f;
}
int n,m,c
,t1
,t2
;
int s
,mp
;
void iniMP(){
sort(mp+1,mp+1+n);
int p=0;mp[++p]=mp[1];
for(int i=2;i<=n;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i];
mp[0]=p;
}
int Bin(int v){
int l=1,r=mp[0];
while(l<=r){
int mid=(l+r)>>1;
if(v==mp[mid]) return mid;
else if(v<mp[mid]) r=mid-1;
else l=mid+1;
}
return 0;
}

int sa
,rnk
,height
;
inline bool cmp(int *r,int a,int b,int j){
return a+j<=n&&b+j<=n&&r[a]==r[b]&&r[a+j]==r[b+j];
}
void getSA(int s[]){
m=mp[0];
int *r=t1,*k=t2;
for(int i=0;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) c[r[i]=s[i]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) sa[c[r[i]]--]=i;

for(int j=1;j<=n;j<<=1){
int p=0;
for(int i=n-j+1;i<=n;i++) k[++p]=i;
for(int i=1;i<=n;i++) if(sa[i]>j) k[++p]=sa[i]-j;

for(int i=0;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) c[r[k[i]]]++;
for(int i=1;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) sa[c[r[k[i]]]--]=k[i];

swap(r,k);p=0;r[sa[1]]=++p;
for(int i=2;i<=n;i++) r[sa[i]]=cmp(k,sa[i],sa[i-1],j)?p:++p;
if(p>=n) break;m=p;
}
}

void solve(){
reverse(s+1,s+1+n);
getSA(s);
int p=1;
while(sa[p]<=2) p++;
for(int i=sa[p];i<=n;i++) printf("%d\n",mp[s[i]]);

n=sa[p]-1;
for(int i=1;i<=n;i++) s[i+n]=s[i];
n<<=1;
getSA(s);
p=1;
n>>=1;
while(sa[p]==1||sa[p]>n) p++;
for(int i=sa[p];i<=n;i++) printf("%d\n",mp[s[i]]);
for(int i=1;i<sa[p];i++) printf("%d\n",mp[s[i]]);
}

int main(){
freopen("in","r",stdin);
n=read();
for(int i=1;i<=n;i++) s[i]=mp[i]=read();
iniMP();
for(int i=1;i<=n;i++) s[i]=Bin(s[i]);
solve();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: