bzoj4278

来源:互联网 发布:apple mac book pro 编辑:程序博客网 时间:2024/06/16 19:19

题意

给定两个数字串A和B,要求归并得到一个字典序最小的数字串T(长度<200000)

分析

(大水题)
a1,a2,a3...an,1001,b1,b2,b3...bm,0
搞一波后缀数组,再用两指针扫一遍就好了。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=1001000;int sa[N],tsa[N],rk[N],trk[N],sum[N];int len1,len2,cnt,m,s[N];int main(){    freopen("a.in","r",stdin);    scanf("%d",&len1);    for (int i=1;i<=len1;i++)        scanf("%d",s+i);    scanf("%d",&len2);s[len1+1]=1001;    for (int i=len1+2;i<=len1+len2+1;i++)        scanf("%d",s+i);s[len1+len2+2]=0;    int len=len1+len2+2;    for (int i=1;i<=len;i++) sum[s[i]]++;    for (int i=1;i<=1001;i++) sum[i]+=sum[i-1];    for (int i=len;i;i--) sa[sum[s[i]]--]=i;    rk[sa[1]]=1;cnt=1;    for (int i=2;i<=len;i++){        if (s[sa[i]]!=s[sa[i-1]]) cnt++;        rk[sa[i]]=cnt;    }m=cnt;    for (int j=1;m<len;j*=2){        cnt=0;        memset(sum,0,sizeof(sum));        memmove(trk,rk,sizeof(rk));        for (int i=len-j+1;i<=len;i++) tsa[++cnt]=i;        for (int i=1;i<=len;i++)             if (sa[i]>j) tsa[++cnt]=sa[i]-j;        for (int i=1;i<=len;i++) sum[ trk[tsa[i]] ]++;        for (int i=1;i<=m;i++) sum[i]+=sum[i-1];        for (int i=len;i;i--) sa[sum[ trk[tsa[i]] ]--]=tsa[i];        rk[sa[1]]=1;cnt=1;        for (int i=2;i<=len;i++){            if (trk[sa[i]]!=trk[sa[i-1]] || trk[sa[i]+j]!=trk[sa[i-1]+j]) cnt++;            rk[sa[i]]=cnt;        }m=cnt;    }    int t1=1,t2=2+len1;    for (int i=1;i<=len-2;i++){        if (t1==len1+1) printf("%d ",s[t2]),t2++; else        if (t2==len1+len2+2) printf("%d ",s[t1]),t1++; else        if (rk[t1]<rk[t2]) printf("%d ",s[t1]),t1++; else        printf("%d ",s[t2]),t2++;    }    printf("\n");}
0 0
原创粉丝点击