• POJ3581 Sequence —— 后缀数组


    题目链接:https://vjudge.net/problem/POJ-3581

    Sequence
    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 7754   Accepted: 1761
    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}

    Source

    题意:

    给出一个字符串,将其分成三段,并且将每一段翻转。求翻转过后字典序最小的一个。

    题解:

    1.分成三段,即求出两个分割点,于是分两部分进行求解。

    2.第一部分:求第一段。由于求的是翻转过后字典序最小的,那么先将原字符串翻转得到逆串,然后求其后缀数组。那么排名最靠前且满足能分成三段的那个后缀,即为翻转过后的第一段。 形如:1 1 2 2 3 3 等最小值重复出现在前面的串,如果直接求其逆串的后缀数组,那么排名最靠前的是“1”,而我们的目标是“1 1”,但题目说明了 A1>A2……An,因此不会出现这种情况。

    3.第二部分:将剩余的逆串复制多一分接在后面,然后求其后缀数组,接下来的做法与第一步类似。

    4. 为什么第二部分需要复制多一份在末尾,而第一部分不用呢?

    答:由于题目声明了A1>A2……An,所以直接求其后缀数组,并得到排名最靠前且满足能分成三段的那个后缀,因为不会出现形如“1 1 2 2 3 3”的串,所以这个后缀一定是最优的;然而,去掉第一段之后,剩下的逆串的原串就可能为类似“1 1 2 2 3 3”的串,即逆串为“3 3 2 2 1 1”,如果直接求其后缀数组,那么得到的第二段为“1”,而我们的目标是“1 1”。为了解决这个问题,可以复制多一份接在后面得到“3 3 2 2 1 1 3 3 2 2 1 1”,然后求后缀数组,取位置在0~len-1且排名靠前且满足能分成两段的。

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 using namespace std;
     13 typedef long long LL;
     14 const int INF = 2e9;
     15 const LL LNF = 9e18;
     16 const int MOD = 1e9+7;
     17 const int MAXN = 4e5+100;
     18 
     19 bool cmp(int *r, int a, int b, int l)
     20 {
     21     return r[a]==r[b] && r[a+l]==r[b+l];
     22 }
     23 
     24 int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
     25 int t1[MAXN], t2[MAXN], c[MAXN];
     26 void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
     27 {
     28     n++;
     29     int i, j, p, *x = t1, *y = t2;
     30     for(i = 0; i<m; i++) c[i] = 0;
     31     for(i = 0; i<n; i++) c[x[i] = str[i]]++;
     32     for(i = 1; i<m; i++) c[i] += c[i-1];
     33     for(i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
     34     for(j = 1; j<=n; j <<= 1)
     35     {
     36         p = 0;
     37         for(i = n-j; i<n; i++) y[p++] = i;
     38         for(i = 0; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j;
     39 
     40         for(i = 0; i<m; i++) c[i] = 0;
     41         for(i = 0; i<n; i++) c[x[y[i]]]++;
     42         for(i = 1; i<m; i++) c[i] += c[i-1];
     43         for(i = n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i];
     44 
     45         swap(x, y);
     46         p = 1; x[sa[0]] = 0;
     47         for(i = 1; i<n; i++)
     48             x[sa[i]] = cmp(y, sa[i-1], sa[i], j)?p-1:p++;
     49 
     50         if(p>=n) break;
     51         m = p;
     52     }
     53 
     54     int k = 0;
     55     n--;
     56     for(i = 0; i<=n; i++) Rank[sa[i]] = i;
     57     for(i = 0; i<n; i++)
     58     {
     59         if(k) k--;
     60         j = sa[Rank[i]-1];
     61         while(str[i+k]==str[j+k]) k++;
     62         height[Rank[i]] = k;
     63     }
     64 }
     65 
     66 int a[MAXN], M[MAXN];
     67 int main()
     68 {
     69     int n;
     70     scanf("%d", &n);
     71     for(int i = 0; i<n; i++)
     72         scanf("%d", &a[i]);
     73     memcpy(M, a, sizeof(M));
     74     sort(M, M+n);
     75     int m = unique(M, M+n)-M;
     76     for(int i = 0; i<n; i++)    //离散化
     77         r[i] = upper_bound(M, M+m, a[i])-M;
     78     reverse(r, r+n);
     79 
     80     int pos1, pos2;
     81     r[n] = m+1;     //在翻转过后的串尾加个最大值,以保证 “1 1 2 2 3 3” 的情况下第一段取的是“2 2”, 而不是“2”
     82     r[n+1] = 0;     //再加上串尾结束符
     83     DA(r, sa, Rank, height, n+1, m+2);
     84     for(int i = 1; i<=n; i++)
     85         if(n-1-sa[i]<=n-3)  //第一段至多只能到n-3的地方,不然就不能分成三段了
     86         {
     87             pos1 = n-1-sa[i];
     88             break;
     89         }
     90 
     91     int len = n-pos1-1;
     92     for(int i = 0; i<len; i++)  //将剩下的串复制多一份接在后面,中间无需分隔符。
     93         r[len+i] = r[i];
     94     len *= 2;
     95     r[len] = 0;
     96     DA(r, sa, Rank, height, len, m+2);
     97     for(int i = 1; i<=len; i++)
     98         if(sa[i]<len/2 && n-sa[i]-1<=n-2) //第二段至多只能到n-2的地方,不然就将剩下的分成两段了
     99         {
    100             pos2 = n-sa[i]-1;
    101             break;
    102         }
    103 
    104 //    printf("%d %d
    ", pos1, pos2);
    105     for(int i = pos1; i>=0; i--) printf("%d
    ", a[i]);
    106     for(int i = pos2; i>pos1; i--) printf("%d
    ", a[i]);
    107     for(int i = n-1; i>pos2; i--) printf("%d
    ", a[i]);
    108 }
    View Code
  • 相关阅读:
    python_day_5:20180720
    python_day_4:20180719
    2018悦读
    2018生活
    心理画
    js 策略模式
    js 单例模式
    js 模板方法模式
    C语言-数据类型
    js 观察者模式
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8480426.html
Copyright © 2020-2023  润新知