• POJ 3581 Sequence(后缀数组)


    【题目链接】 http://poj.org/problem?id=3581

     

    【题目大意】

      给出一个数列,将这个数列分成三段,每段分别翻转,使得其字典序最小,输出翻转后的数列。

     

    【题解】

      首先,第一个翻转点就是翻转后数列的最小后缀,注意由于一定要分成三段,则至少要剩下两个元素。难点主要是如何处理第二个翻转点,我们发现剩余的部分的每一种翻转拆分都是将两串翻转后剩余部分拼接在一起得到的串的子串,所以我们将剩余部分翻转,复制一份拼接在后面,求最小后缀即可。

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N=800010;
    int n,rank[N],sa[N],h[N],tmp[N],cnt[N],ans; int s[N]; 
    void suffixarray(int n,int m){
        int i,j,k;n++;
        for(i=0;i<2*n+5;i++)rank[i]=sa[i]=h[i]=tmp[i]=0;
        for(i=0;i<m;i++)cnt[i]=0;
        for(i=0;i<n;i++)cnt[rank[i]=s[i]]++;
        for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
        for(i=0;i<n;i++)sa[--cnt[rank[i]]]=i;
        for(k=1;k<=n;k<<=1){
            for(i=0;i<n;i++){
                j=sa[i]-k;
                if(j<0)j+=n;
                tmp[cnt[rank[j]]++]=j;
            }sa[tmp[cnt[0]=0]]=j=0;
            for(i=1;i<n;i++){
                if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k])cnt[++j]=i;
                sa[tmp[i]]=j;
            }memcpy(rank,sa,n*sizeof(int));
            memcpy(sa,tmp,n*sizeof(int));
            if(j>=n-1)break;
        }for(j=rank[h[i=k=0]=0];i<n-1;i++,k++)
        while(~k&&s[i]!=s[sa[j-1]+k])h[j]=k--,j=rank[sa[j]+1];
    }
    int disc[N];
    int remark(int x){
    	  int l=1,r=n;
    	  while(l<=r){
    		    int mid=(l+r)>>1;
    		    if(disc[mid]<x)l=mid+1;
    		    else if(disc[mid]==x)return mid;
    		    else r=mid-1;
    	  }
    }
    int a[N],p1,p2;
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",a+i),disc[i+1]=a[i];
        sort(disc+1,disc+n+1);
        for(int i=0;i<n;i++)a[i]=remark(a[i]);
        reverse_copy(a,a+n,s);
        suffixarray(n,n+1);
        for(int i=0;i<=n;i++){p1=n-sa[i];if(p1>=1&&n-p1>=2)break;}
        int m=n-p1;
        reverse_copy(a+p1,a+n,s);
        reverse_copy(a+p1,a+n,s+m);
        suffixarray(m<<1,n+1);
        for(int i=0;i<=2*m;i++){p2=p1+m-sa[i];if(p2>p1&&n>p2)break;}
        reverse(a,a+p1);reverse(a+p1,a+p2);reverse(a+p2,a+n);
        for(int i=0;i<n;i++)printf("%d
    ",disc[a[i]]);
        return 0;
    }
    

      

  • 相关阅读:
    【 DCOS 】织云 CMDB 管理引擎技术详解
    腾讯云无服务器云函数架构精解
    深度学习在 CTR 中应用
    一文教你迅速解决分布式事务 XA 一致性问题
    小程序开发工具全新上线
    秦俊:开放 DevOps 敏捷开发套件,助力开发者驰骋云端
    张兴华:云端架构助力企业快速成长
    王磊:AI 时代物流行业的 OCR 应用
    陈杰:无服务器架构,让云端开发更纯粹
    腾讯织云:DevOps 流水线应用平台践行之路
  • 原文地址:https://www.cnblogs.com/forever97/p/poj3581.html
Copyright © 2020-2023  润新知