zoukankan      html  css  js  c++  java
  • Locker Room Gym

    题意:

    在长度为 N 的主串中选取一个长度为 K 的子串可以把原主串全覆盖。覆盖的条件是 选取的子串 s 把原串中所有长度为 K 并且字典序小于 s 的子串的字符标记之后(每个字符可被标记多次),

    如果原串的全部字符都被标记,则当前选取的子串 s 可以覆盖这个主串。

    求字典序最小的 s 。原串是一个环!!!即最小化最大值。

    思路:后缀数组,直接开2倍长度跑SA就好了,因为我们要找一个满足能标记完n个字符的排名最小的长度为k的子串,所以我们可以二分排名check一下长度是否大于等于n就好了。

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    //#define _for(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    typedef long long ll;
    double eps=0.05;
    ll mod=1e9+7;
    const int INF=0x3f3f3f3f,inf =0x3f3f3f3f;
    const int MAXN=2e3+10;
    const int maxn = 1e7+10;
    //ll inf=100000000000000;
    //template<typename T>inline void read(T &x)
    //{
    //    x=0;
    //    static int p;p=1;
    //    static char c;c=getchar();
    //    while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
    //    while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
    //   x*=p;
    //}
    typedef unsigned long long ull;
    const int N=2e6+7;
    const double PI=acos(-1.0);
    char ss[N];
    int s[N];
    int sa[N],t[N],t2[N],c[N];//y[N];
    int rk[N],H[N];
    void build_sa(int n,int m){
        int i,*x=t,*y=t2;
        for( i=0;i<m;i++)c[i]=0;
        for( i=0;i<n;i++)c[x[i]=s[i]]++;
        for( i=1;i<m;i++)c[i]+=c[i-1];
        for( i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
        for(int k=1;k<=n;k<<=1){
            int p=0;
            for(i=n-k;i<n;i++)y[p++]=i;
            for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
            for(i=0;i<m;i++)c[i]=0;
            for(i=0;i<n;i++)c[x[y[i]]]++;
            for(i=0;i<m;i++)c[i]+=c[i-1];
            for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(i=1;i<n;i++)
                x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
            if(p>=n)break;
            m=p;
        }
    }
    void getH(int n){
        int i,j,k=0;
        for(i=0;i<n;i++)rk[sa[i]]=i;
        for(i=0;i<n;i++){
            if(k)k--;
            int j=sa[rk[i]-1];
            while(s[i+k]==s[j+k])k++;
            H[rk[i]]=k;
        }
    }
    //void SA(int n,int m){
    //    for(int i=0;i<m;i++) c[i]=0;
    //    for(int i=0;i<n;i++) c[rk[i]=s[i]]++;
    //    for(int i=1;i<m;i++) c[i]+=c[i-1];
    //    for(int i=n-1;i>=0;i--) sa[--c[rk[i]]]=i;
    //    for(int k=1;k<=n;k<<=1){
    //        int num=0;
    //        for(int i=n-k;i<n;i++) y[num++]=i;
    //        for(int i=0;i<n;i++) if(sa[i]>=k) y[num++]=sa[i]-k;
    //        for(int i=0;i<m;i++) c[i]=0;
    //        for(int i=0;i<n;i++) c[rk[i]]++;
    //        for(int i=1;i<m;i++) c[i]+=c[i-1];
    //        for(int i=n-1;i>=0;i--)
    //            sa[--c[rk[y[i]]]]=y[i];
    //        swap(rk,y);
    //        rk[sa[0]]=0; num=1;
    //        for(int i=1;i<n;i++)
    //            rk[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k] ? num-1:num++);
    //        if(num>=n) break;
    //        m=num;
    //    }
    //}
    //void HH (int n){
    //    for(int i=1;i<=n;i++) sa[rk[i]]=i;
    //    for(int i=0,k=0;i<n;i++){
    //        if(k) k--; else k=0;
    //        int j=sa[rk[i]-1];
    //        while(s[i+k]==s[j+k]) k++;
    //        H[rk[i]]=k;
    //    }
    //}
    bool check(int mid,int n,int k){
        int st=0,en=-1;
        for(int i=0;i<n;i++){
            if(rk[i]>mid) continue;
            if(en<i) st=i;
            en=i+k;
            if(en-st>=n) return true;
        }
        return false;
    }
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        scanf("%s",ss);
        for(int i=0;i<n;i++)ss[n+i]=ss[i];
        for(int i=0;i<2*n;i++)s[i]=ss[i]-'a'+1;
        n<<=1;
        s[n]=0;
    //    for(int i=0;i<n;i++)printf("%d",s[i]);
    //    cout<<endl;
        build_sa(n+1,30);
        //SA(n+1,30);
        getH(n+1);
        //HH(n);
    //    for(int i=0;i<n;i++){
    //        printf("%d ",sa[i]);
    //    }
    //    cout<<endl;
    //    for(int i=0;i<n;i++){
    //        printf("%d ",rk[i]);
    //    }
    //    cout<<endl;
        int l=0,r=n,ans;
        while(l<=r){
            int mid = (l+r)>>1;
            if(check(mid,n,k)) r=mid-1,ans=mid;
            else l=mid+1;
        }
        for(int i=0;i<n;i++){
            if(rk[i]==ans){
                for(int j=i;j<i+k;j++)
                    printf("%c",ss[j]);
                return 0;
            }
        }
    //    int l=0,r=n,ans;
    //    while(l<=r){
    //        int mid=(l+r)>>1;
    //        if(check(mid,n,k))r=mid-1,ans=mid;
    //        else l=mid+1;
    //    }
    //    cout<<ans<<endl;
    //    cout<<ss<<endl;
    //    for(int i=0;i<n;i++){
    //        if(rk[i]==ans){
    //                cout<<i<<" "<<i+k<<endl;
    //            for(int j=i;j<i+k;j++){
    //                printf("%c",ss[j]);
    //            }
    //            return 0;
    //        }
        //}
        return 0;
    }
    View Code
  • 相关阅读:
    循环选择判断文件类型
    SpringBoot+MyBatis+Mysql+Durid实现动态多数据源
    Spring 常用注解
    Spring IOC容器中那些鲜为人知的细节
    java8 Stream对List<Map>的分组合并操作
    Java8的CompletableFuture 使用详解
    Spring MVC源码分析
    Spring AOP源码分析
    Spring中AOP必须明白的几个概念
    UriComponentsBuilder和UriComponents url编码
  • 原文地址:https://www.cnblogs.com/kayiko/p/13618446.html
Copyright © 2011-2022 走看看