zoukankan      html  css  js  c++  java
  • POJ3581:Sequence(后缀数组)

    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}

    题意:把数组分成3分,每一份都翻转。要求输出字典序最小的结果

    第二次求之所以要复制一次我们能够这样理解
    首先320505。单纯这个的话,后缀按字典序排,第一是05,第二是0505
    可是复制了之后,是第一是0505320505,第二是05320505
    可见复制一遍还是有必要的

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <math.h>
    #include <bitset>
    #include <algorithm>
    #include <climits>
    using namespace std;
    
    #define LS 2*i
    #define RS 2*i+1
    #define UP(i,x,y) for(i=x;i<=y;i++)
    #define DOWN(i,x,y) for(i=x;i>=y;i--)
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define W(a) while(a)
    #define gcd(a,b) __gcd(a,b)
    #define LL long long
    #define N 2000005
    #define MOD 1000000007
    #define INF 0x3f3f3f3f
    #define EXP 1e-8
    int wa[N],wb[N],wsf[N],wv[N],sa[N];
    int rank[N],height[N],s[N];
    //sa:字典序中排第i位的起始位置在str中第sa[i]
    //rank:就是str第i个位置的后缀是在字典序排第几
    //height:字典序排i和i-1的后缀的最长公共前缀
    int cmp(int *r,int a,int b,int k)
    {
        return r[a]==r[b]&&r[a+k]==r[b+k];
    }
    void getsa(int *r,int *sa,int n,int m)//n要包括末尾加入的0
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0; i<m; i++)  wsf[i]=0;
        for(i=0; i<n; i++)  wsf[x[i]=r[i]]++;
        for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
        for(i=n-1; i>=0; i--)  sa[--wsf[x[i]]]=i;
        p=1;
        j=1;
        for(; 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++)  wsf[i]=0;
            for(i=0; i<n; i++)  wsf[wv[i]]++;
            for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
            for(i=n-1; i>=0; i--)  sa[--wsf[wv[i]]]=y[i];
            t=x;
            x=y;
            y=t;
            x[sa[0]]=0;
            for(p=1,i=1; i<n; i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
        }
    }
    
    struct node
    {
        int id,num;
    } a[N];
    
    int cmp1(node a,node b)
    {
        if(a.num!=b.num)
            return a.num<b.num;
        return a.id<b.id;
    }
    
    int main()
    {
        int n,i,j,k,maxn;
        scanf("%d",&n);
        for(i = n-1; i>=0; i--)
        {
            scanf("%d",&a[i].num);
            a[i].id = i;
        }
        sort(a,a+n,cmp1);
        for(i = 0; i<n; i++)
        {
            if(i && a[i].num == a[i-1].num)
            {
                s[a[i].id] = s[a[i-1].id];
                continue;
            }
            s[a[i].id] = i+1;
        }
        s[n] = 0;
        getsa(s,sa,n+1,n+10);
        for(i = 1; i<=n&&sa[i]<=1; i++);
    
        int tem = sa[i];
        for(i = tem; i<n; i++)
            printf("%d
    ",a[s[i]-1].num);
        for(i = 0; i<tem; i++)
            s[i+tem] = s[i];
        tem*=2;
        s[tem] = 0;
        getsa(s,sa,tem+1,n+10);
        int p;
        for(i = 1; i<tem&&(!sa[i]||sa[i]>=tem/2); i++) ;
        p = sa[i];
        for(i = p; i<tem/2; i++)
            printf("%d
    ",a[s[i]-1].num);
        for(i = 0; i<p; i++)
            printf("%d
    ",a[s[i]-1].num);
    
    
        return 0;
    }
    


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    EV录屏
    Oracle 游标详解 【转载至CSDN「鱼丸丶粗面」】
    ORACLE查询表数据占用存储空间大小(清理表碎片)
    开源项目
    Shiro 简介(认证、授权、加密、会话管理、与 Web 集成、缓存等)
    OSCHINA 公布 2019 年度最受欢迎中国开源软件
    腾讯开发者手册
    hutool JAVA 工具类
    小程序登录
    微信小程序button组件样式
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4907681.html
Copyright © 2011-2022 走看看