bzoj4278

题意

给定两个数字串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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值