zoukankan      html  css  js  c++  java
  • Sequence POJ

    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
    ",ss[i]);
    103     for(int i=pos2; i<pos1; i++)printf("%d
    ",ss[i]);
    104     for(int i=0; i<pos2; i++)printf("%d
    ",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
     
  • 相关阅读:
    Linux——配置secureCRT远程连接图形化显示
    Oracle——insert ino,insert all into,insert first into
    Mysql——case函数
    Mysql——语句执行顺序
    Mysql——实现按字段部分升序,部分降序的方法
    无线网ping虚拟机
    http协议
    eclipse——32位64位Eclipse和jdk对应关系
    2019-07-24_windows系统一些常用的dos命令
    2019-07-23_zabbix监控安装视频教程
  • 原文地址:https://www.cnblogs.com/iwannabe/p/11483169.html
Copyright © 2011-2022 走看看