zoukankan      html  css  js  c++  java
  • 【bzoj4486】【JSOI2015】串分割

    老省选题了。

    首先考虑怎么比较超长数字的大小?

    参见UTR1的那道题

    先比size,然后比较字典序即可。

    接下来考虑下切割的问题。

    因为要将字符串切割成k份,所以这个字符串只会存在n/k个本质不同的起始位置。

    然后可能会发现,如果能够整除的话,将这些起始位置直接后缀排序就可以了。

    那么如果不能整除怎么办?

    我们可以发现,如果有多余的,那么最长的字符串一定最多比别人多1

    这个贪心的正确性比较的显然。

    那么我们怎么处理长度不同的呢?

    将之前的比较二分即可。

    #include<bits/stdc++.h>
    #define N 400010
    using namespace std;
    int t1[N],t2[N],a[N],sa[N],rk[N],c[20],h[N];
    int n,m,k,cnt;
    char s[N];
    void calcsa(int n,int m){
        int *x=t1,*y=t2,f=0,p=0;
        for(int i=1;i<=m;i++)c[i]=0;
        for(int i=1;i<=n;i++)c[x[i]=a[i]]++;
        for(int i=1;i<=m;i++)c[i]+=c[i-1];
        for(int i=n;i;i--)sa[c[x[i]]--]=i;
        for(int i=1;i<=n&&p<=n;i<<=1){p=0;
            for(int j=n-i+1;j<=n;j++)y[++p]=j;
            for(int j=1;j<=n;j++)if(sa[j]>i)y[++p]=sa[j]-i;
            for(int j=1;j<=m;j++)c[j]=0;
            for(int j=1;j<=n;j++)c[x[y[j]]]++;
            for(int j=1;j<=m;j++)c[j]+=c[j-1];
            for(int j=n;j>=1;j--)sa[c[x[y[j]]]--]=y[j];
            swap(x,y);x[sa[1]]=1;p=2;
            for(int j=2;j<=n;j++)
            x[sa[j]]=y[sa[j]]==y[sa[j-1]]&&y[sa[j]+i]==y[sa[j-1]+i]?p-1:p++;
            m=p;
        }
        for(int i=1;i<=n;i++)rk[sa[i]]=i;
        for(int i=1;i<=n;i++){
            int j=sa[rk[i]-1];
            if(f)f--;while(a[i+f]==a[j+f])f++;
            h[rk[i]]=f;
        }
    }
    inline bool check(int x){
        int p;
        for(int i=1;i<=m;i++){
            int t=i;p=k;
            while(p--){
                if(rk[t]<=x)t+=m;else t+=m-1;
                if(t>=n+i)return 1;
            }
        }
        return 0;
    }
    inline void work(){
        int l=1,r=cnt;
        while(l<r){
            int mid=(l+r)>>1;
            if(check(mid))r=mid;else l=mid+1;
        }
        for(int i=1;i<=n;i++)if(rk[i]==l)
        for(int j=i;j<=i+m-1;j++)printf("%c",a[j]+'1');
        puts("");
    }
    int main(){
        scanf("%d%d",&n,&k);scanf("%s",s+1);
        for(int i=1;i<=n;i++)a[++cnt]=s[i]-'1';
        for(int i=1;i<n;i++)a[++cnt]=s[i]-'1';
        calcsa(cnt,10);
        //for(int i=1;i<=cnt;i++)printf("%d ",sa[i]);puts("");
        m=n/k+(n%k!=0);
        work();
    }
  • 相关阅读:
    GGEditor
    Vue 项目(HTML5 History 模式) 部署服务器
    mysql连接状态
    mysql连接状态
    HBase配置性能调优
    HBase配置性能调优
    spark streaming检查点使用
    spark streaming检查点使用
    spark streaming的有状态例子
    spark streaming的有状态例子
  • 原文地址:https://www.cnblogs.com/zcysky/p/7351032.html
Copyright © 2011-2022 走看看