码迷,mamicode.com
首页 > 编程语言 > 详细

Sequence POJ - 3581 (后缀数组)

时间:2019-09-07 22:41:07      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:rev   std   style   oid   mat   sample   using   names   fir   

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}
 
题意:给一个序列,分成三段,并且将其反转,求出最小的序列
 
思路:
由于字典序,所以尽量让前面的小。
利用后缀数组ht数组的性质,将原串反转,求出第一个符合要求的ht下标,即我们可以求出第一个分割点的位置(要求:当前位置必须 < n-2)
然后就只剩下一个分割点了,对于这个分割点,我们不能直接继续求最小值,因为对于 8 -1 4 1 1 4 1 1 2 这样的序列,我们继续求会求出深色位置,这样是错的,因为对于后缀数组,其相等时是将短的排在前面,但是对于我们反转来说由于前部分
相等,所以后部分可能是长的更优秀
这样我们可以想到,对一个点前面的串反转,且将后面的串反转后,就相当于1  1 4 2 1 1 4,是不是发现了什么,对于每个位置反转都是如此,那么我们可以
将 串构造成4 1 1 4 1 1 2 4 1 1 4 1 1 2,这样再求一次最小位置且满足要求的即可
 
技术图片
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<vector>
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 const int maxn = 4e5+10;
 10 int s[maxn];
 11 int ss[maxn];
 12 int sa[maxn],t[maxn],t2[maxn],c[maxn];
 13 
 14 void build_sa(int n,int m)
 15 {
 16     int i,*x=t,*y=t2;
 17     for(i=0; i<m; i++)c[i]=0;
 18     for(i=0; i<n; i++)c[x[i]=s[i]]++;
 19     for(i=1; i<m; i++)c[i]+=c[i-1];
 20     for(i=n-1; i>=0; i--)sa[--c[x[i]]]=i;
 21     for(int k=1; k<=n; k<<=1)
 22     {
 23         int p=0;
 24         for(i=n-k; i<n; i++)y[p++]=i;
 25         for(i=0; i<n; i++)if(sa[i] >= k)y[p++]=sa[i]-k;
 26         for(i=0; i<m; i++)c[i] = 0;
 27         for(i=0; i<n; i++)c[x[y[i]]]++;
 28         for(i=1; i<m; i++)c[i]+=c[i-1];
 29         for(i=n-1; i>=0; i--)sa[--c[x[y[i]]]] = y[i];
 30         swap(x,y);
 31         p=1,x[sa[0]]=0;
 32         for(i=1; i<n; i++)
 33             x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k]?p-1:p++;
 34         if(p>=n)break;
 35         m=p;
 36     }
 37 }
 38 
 39 int ht[maxn],rk[maxn];
 40 
 41 void getHeight(int n)
 42 {
 43     int i,j,k=0;
 44     for(i=1; i<=n; i++)rk[sa[i]] = i;
 45     for(i=0; i<n; i++)
 46     {
 47         if(k)k--;
 48         int j = sa[rk[i]-1];
 49         while(s[i+k] == s[j+k] && s[i+k] != $)k++;
 50         ht[rk[i]] = k;
 51     }
 52 }
 53 int n;
 54 vector<int>v;
 55 
 56 int cmp(int *s,int pos1,int pos2,int len)
 57 {
 58     for(int i=0; i<len; i++)
 59     {
 60         if(s[pos1+i] < s[pos2+i])return -1;
 61         if(s[pos1+i] > s[pos2+i])return 1;
 62     }
 63     return 0;
 64 }
 65 
 66 int main()
 67 {
 68     scanf("%d",&n);
 69     v.clear();
 70     for(int i=0; i<n; i++)scanf("%d",&ss[i]),v.push_back(ss[i]);
 71     reverse(ss,ss+n);
 72     sort(v.begin(),v.end());
 73     v.erase(unique(v.begin(),v.end()),v.end());
 74     for(int i=0; i<n; i++)s[i] = lower_bound(v.begin(),v.end(),ss[i])-v.begin()+1;
 75     s[n] = 0;
 76     build_sa(n+1,maxn);
 77     getHeight(n);
 78     int pos1 = 0;
 79     int pos2 = 0;
 80     for(int i=1; i<=n; i++)
 81     {
 82         if(sa[i] > 1)
 83         {
 84             pos1 = sa[i];
 85             break;
 86         }
 87     }
 88     for(int i=0; i<pos1; i++)s[pos1+i] = s[i];
 89     int fn = 2*pos1;
 90     s[fn] = 0;
 91    // cout << pos1 << endl;
 92     build_sa(fn+1,maxn);
 93     getHeight(fn);
 94     for(int i=1; i<=fn; i++)
 95     {
 96         if(sa[i] > 0 && sa[i] < pos1)
 97         {
 98             pos2 = sa[i];
 99             break;
100         }
101     }
102     for(int i=pos1; i<n; i++)printf("%d\n",ss[i]);
103     for(int i=pos2; i<pos1; i++)printf("%d\n",ss[i]);
104     for(int i=0; i<pos2; i++)printf("%d\n",ss[i]);
105 }
106 
107 /*
108 9
109 9 -2 8 1 1 8 1 1 1
110 
111 9
112 9 -2 8 1 1 8 1 1 2
113 */
View Code

 

 

Sequence POJ - 3581 (后缀数组)

标签:rev   std   style   oid   mat   sample   using   names   fir   

原文地址:https://www.cnblogs.com/iwannabe/p/11483169.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!