zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    用bower命令创建项目
    HBuilder打包ios应用
    响应式布局--引入外部样式
    手机中点击链接或button按钮出现黄色边框的解决办法
    通过输入卡号前10位数字判断是哪个银行的卡和类型(储蓄卡or信用卡)
    只允许输入数字和小数点
    python中的实例方法、静态方法、类方法、类变量和实例变量浅析
    python中的实例方法、静态方法、类方法、类变量和实例变量浅析
    python导入csv文件出现SyntaxError问题分析
    python导入csv文件出现SyntaxError问题分析
  • 原文地址:https://www.cnblogs.com/WABoss/p/5243398.html
Copyright © 2011-2022 走看看