zoukankan      html  css  js  c++  java
  • 【BZOJ-4278】Tasowanie 后缀数组 + 归并

    4278: [ONTAK2015]Tasowanie

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 164  Solved: 80
    [Submit][Status][Discuss]

    Description

    给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T。

    Input

    第一行包含一个正整数n(1<=n<=200000),表示A串的长度。
    第二行包含n个正整数,其中第i个数表示A[i](1<=A[i]<=1000)。
    第三行包含一个正整数m(1<=m<=200000),表示B串的长度。
    第四行包含m个正整数,其中第i个数表示B[i](1<=B[i]<=1000)。

    Output

    输出一行,包含n+m个正整数,即字典序最小的T串。

    Sample Input

    6
    1 2 3 1 2 4
    7
    1 2 2 1 3 4 3

    Sample Output

    1 1 2 2 1 2 3 1 2 3 4 3 4

    HINT

    Source

    By Claris

    Solution

    一眼秒后缀数组裸题?算出rank数组来

    二路归并的输出答案即可....

    PS感觉Claris不会传裸题上来的,于是%了发他的做法,是个贪心

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define maxn 400010
    int len,val[maxn];
    int S[maxn]; int SA[maxn];
    int ws[maxn],wa[maxn],wv[maxn],wb[maxn];
    int cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void DA(int *r,int *sa,int n,int m)
    {
        int p,*x=wa,*y=wb,*t;
        for (int i=0; i<m; i++) ws[i]=0;
        for (int i=0; i<n; i++) ws[x[i]=r[i]]++;
        for (int i=1; i<m; i++) ws[i]+=ws[i-1];
        for (int i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
        p=1; for (int j=1; p<n; j*=2,m=p)
            {
                p=0; for (int i=n-j; i<n; i++) y[p++]=i;
                for (int i=0; i<n; i++) if (sa[i]>=j) y[p++]=sa[i]-j;
                for (int i=0; i<n; i++) wv[i]=x[y[i]];
                for (int i=0; i<m; i++) ws[i]=0;
                for (int i=0; i<n; i++) ws[wv[i]]++;
                for (int i=1; i<m; i++) ws[i]+=ws[i-1];
                for (int i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
                t=x; x=y; y=t; p=1; x[sa[0]]=0;
                for (int i=1; i<n; i++) 
                    x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
            } 
    }
    int rank[maxn],height[maxn];
    void calheight(int *r,int *sa,int n)
    {
        int k=0;
        for (int i=1; i<=n; i++) rank[sa[i]]=i;
        for (int i=0; i<n; height[rank[i++]]=k)
            {k?k--:0;for (int j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);}
    }
    int N,M;
    int main()
    {
        N=read();
        for (int i=0; i<N; i++) S[i]=read(); S[N]=1001;
        M=read();
        for (int i=1; i<=M; i++) S[i+N]=read(); S[N+M+1]=0;
        DA(S,SA,N+M+2,1002); calheight(S,SA,N+M+1); 
        int a=0,b=N+1;
        for (int i=0; i<=N+M; i++)
            {
                if (i==N) continue;
                if (a==N) {for (int j=b; j<=N+M; j++) printf("%d ",S[j]); break;} 
                if (b==N+M+1) {for (int j=a; j<N; j++) printf("%d ",S[j]); break;}
                if (rank[a]<rank[b]) printf("%d ",S[a]),a++;
                    else printf("%d ",S[b]),b++;
            }
        return 0;
    }

    跑得怎么比hs(hen)y快这么多..但还是被卡第一页了....

  • 相关阅读:
    怎样写C代码——《狂人C》习题解答1——余响
    怎样写C代码——《狂人C》习题解答1(第一章习题7)
    充分理解表达式——《狂人C》习题解答2(第二章习题5)
    指针——《狂人C》观点
    欧拉项目练习题吧: 题目002
    JS调用XML绑定select[原创]
    SWFUpload在FF下的Bug[原创]
    winform实现嵌套类访问父类的控件[原创]
    在c#中如何动态改变iframe的src值,动态指向一个网页
    GridView里面模板获取唯一值(如ID)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5487450.html
Copyright © 2011-2022 走看看