pku3581 Sequence

搞掂这题我用了三张草稿纸。。。这得感谢我的小学班主任黄向阳老师,您在我毕业的时候塞给我的n叠作文纸,直到现在还没用完,搞得我每撕一张就想您一次。。。

(省略一万字)

说说我的做法,这题用后缀数组不难想,但要注意以下几点:

1,假设要分开的是两段而不是三段,看看以下两个数据:

      2 1 2 1 3    ->   1 2 1 2 3 (1)

      2 1 2 1 0    ->   1 2 0 1 2 (2)

    看得出两个数据分段的地方不一样。可以试一试最后的数字分别是0、1、2、3的情况,会发现当最后的数字大于等于3时有最小字典序的串按(1)来分段,小于3时按(2)来分段,也就是说分段情况是由最后一个数字决定的。有了这个结论,我的做法是先将原串置反,然后将逆串的第一个数字加到逆串的末尾跑后缀数组,得出的长度不大于原串长度-2的最小后缀就是第一段输出。从逆串中去掉第一段后再按以上步骤得出第二段输出,剩下的就是第三段了。总共跑了两趟后缀数组。这里错了,正解看评论)

2,如果后缀数组当中用到了桶排序,一定要先将串离散化,不然桶装不下。

3,用while(scanf()!=EOF)真的会WA,至于为什么呢我也不清楚。

 

#include <iostream>
#include 
<algorithm>
using namespace std;

#define MAXN 200010

int b[MAXN],array[4][MAXN],*rank,*nrank,*sa,*nsa,n,len;
int seq[MAXN];
int mx;

int num[MAXN],change[MAXN];

void make_sa(){
    
int i,k;
    
    sa
=array[0];
    nsa
=array[1];
    rank
=array[2];
    nrank
=array[3];
    
    memset(b,
0,sizeof(b));
    
for(i=0;i<n;i++)
        b[seq[i]]
++;
    
for(i=1;i<=mx;i++)
        b[i]
+=b[i-1];
    
for(i=n-1;i>=0;i--)
        sa[
--b[seq[i]]]=i;
    
    
for(rank[sa[0]]=0,i=1;i<n;i++){
        rank[sa[i]]
=rank[sa[i-1]];
        
if(seq[sa[i]]!=seq[sa[i-1]])
            rank[sa[i]]
++;
    }
    
    
    
for(k=1;k<&& rank[sa[n-1]]<n-1;k*=2){
        
for(i=0;i<n;i++)
            b[rank[sa[i]]]
=i;
        
        
for(i=n-1;i>=0;i--)
            
if(sa[i]-k>=0)
                nsa[b[rank[sa[i]
-k]]--]=sa[i]-k;
            
            
for(i=n-k;i<n;i++)
                nsa[b[rank[i]]
--]=i;
            
            
for(nrank[nsa[0]]=0,i=1;i<n;i++){
                nrank[nsa[i]]
=nrank[nsa[i-1]];
                
if(rank[nsa[i]]!=rank[nsa[i-1]] || rank[nsa[i]+k]!=rank[nsa[i-1]+k])
                    nrank[nsa[i]]
++;
            }
            
int *t=sa;sa=nsa;nsa=t;
            t
=rank;rank=nrank;nrank=t;
    }
}

class CP{
public:
    
int operator()(int a,int b){
        
return num[a]<num[b];
    }
};

void init(){
    
int i;
    scanf(
"%d",&n);
    mx
=n;//桶排序的范围在1~mx

    
for(i=n-1;i>=0;i--){
        scanf(
"%d",&num[i]);
        b[i]
=i;
    }
    sort(b,b
+n,CP());
    
int m=1;
    seq[b[
0]]=1;
    change[
1]=num[b[0]];
    
for(i=1;i<n;i++){
        
if(num[b[i]]!=num[b[i-1]])
            m
++;
        seq[b[i]]
=m;
        change[m]
=num[b[i]];
    }
}



int main(){
    
int i,cnt,t;
    init();

    seq[n
++]=seq[0];//*
    make_sa();
    t
=0;
    
while(sa[t]==n-1 || sa[t]<=1)t++;
    cnt
=0;
    
for(i=sa[t];i<n-1;i++){
        cnt
++;
        printf(
"%d\n",change[seq[i]]);
    }

    n
-=cnt+1;
    seq[n
++]=seq[0];//*
    make_sa();
    t
=0;
    
while(sa[t]==n-1 || sa[t]<1)t++;
    
for(i=sa[t];i<n-1;i++)
        printf(
"%d\n",change[seq[i]]);
    
for(i=0;i<sa[t];i++)
        printf(
"%d\n",change[seq[i]]);


    
return 0;
}

 

 

posted @ 2009-02-15 17:18  Beetlebum  阅读(576)  评论(8编辑  收藏  举报