• POJ3581 Sequence(后缀数组)


    题意:给一个串,串的第一个字符比后面的都大,要把它分成三段,然后反转每一段,求能得到的字典序最小的串是什么。

    首先,第一段是可以确定的:把原串反转,因为第一个字符是最大的,它是唯一的,不存在反转串的后缀之间有包含关系,所以取最小的后缀这就是第一段的字符串;

    然后后面两段,如果确定分割位置可以发现这两段字符串构成是一个从分割位置出发逆时针循环回来的串——

    即接下来要求的就是剩余部分的反转的最小表示,可以用后缀数组来做:把串加长一倍,答案就在最小的且长度大于等于原串长度的后缀了。

    注意,分的段要非空。。所以还要在第一段、后面两段的分割加些判断。

    这题好难A,不知道为什么。。WA来WA去。。改啊改,终于RE来RE去。。跟着别人把数字离散化后才AC了。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 using namespace std;
     6 #define MAXN 222222
     7 int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];
     8 int cmp(int *r,int a,int b,int l){
     9     return r[a]==r[b] && r[a+l]==r[b+l];
    10 }
    11 int sa[MAXN];
    12 void SA(int *r,int n,int m){
    13     int *x=wa,*y=wb;
    14 
    15     for(int i=0; i<m; ++i) ws[i]=0;
    16     for(int i=0; i<n; ++i) ++ws[x[i]=r[i]];
    17     for(int i=1; i<m; ++i) ws[i]+=ws[i-1];
    18     for(int i=n-1; i>=0; --i) sa[--ws[x[i]]]=i;
    19 
    20     int p=1;
    21     for(int j=1; p<n; j<<=1,m=p){
    22         p=0;
    23         for(int i=n-j; i<n; ++i) y[p++]=i;
    24         for(int i=0; i<n; ++i) if(sa[i]>=j) y[p++]=sa[i]-j;
    25         for(int i=0; i<n; ++i) wv[i]=x[y[i]];
    26         for(int i=0; i<m; ++i) ws[i]=0;
    27         for(int i=0; i<n; ++i) ++ws[wv[i]];
    28         for(int i=1; i<m; ++i) ws[i]+=ws[i-1];
    29         for(int i=n-1; i>=0; --i) sa[--ws[wv[i]]]=y[i];
    30         swap(x,y); x[sa[0]]=0; p=1;
    31         for(int i=1; i<n; ++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    32     }
    33 }
    34 
    35 int a[MAXN],r[MAXN];
    36 int b[MAXN],bn;
    37 int main(){
    38     int n;
    39     scanf("%d",&n);
    40     for(int i=0; i<n; ++i){
    41         scanf("%d",a+i);
    42         b[i]=a[i];
    43     }
    44     sort(b,b+n);
    45     bn=unique(b,b+n)-b;
    46     for(int i=0; i<n; ++i){
    47         a[i]=lower_bound(b,b+bn,a[i])-b+1;
    48     }
    49     for(int i=0; i<n; ++i){
    50         r[i]=a[n-i-1];
    51     }
    52     r[n]=0;
    53     SA(r,n+1,bn+1);
    54     int m=0;
    55     for(int i=1; i<=n; ++i){
    56         if(sa[i]>=2){
    57             for(int j=sa[i]; j<n; ++j){
    58                 printf("%d
    ",b[r[j]-1]);
    59             }
    60             n=sa[i];
    61             for(int j=0; j<sa[i]; ++j){
    62                 r[j+sa[i]]=r[j];
    63                 m+=2;
    64             }
    65             r[m]=0;
    66             break;
    67         }
    68     }
    69     SA(r,m+1,bn+1);
    70     for(int i=1; i<=m; ++i){
    71         if(m-sa[i]>=n && sa[i]!=m/2 && sa[i]!=0){
    72             for(int j=0; j<n; ++j) printf("%d
    ",b[r[sa[i]+j]-1]);
    73             break;
    74         }
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    变量的解构赋值
    vue-progressbar 知识点
    <script>标签里的defer和async属性 区别(待补充)
    管理node.js版本的模块:n
    node 知识点
    让node支持es模块化(export、import)的方法
    jvm 知识点
    前端 术语
    js的严格模式
    commonJS、AMD、es模块化 区别(表格比较)
  • 原文地址:https://www.cnblogs.com/WABoss/p/5243398.html
Copyright © 2020-2023  润新知