• BZOJ4310:跳蚤


    4310: 跳蚤

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 543  Solved: 246
    [Submit][Status][Discuss]

    Description

    很久很久以前,森林里住着一群跳蚤。一天,跳蚤国王得到了一个神秘的字符串,它想进行研究。
    首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个,并在选出来的 k 个子串中选择字典序最大的那一个。他称其为“魔力串”。
    现在他想找一个最优的分法让“魔力串”字典序最小。

    Input

    第一行一个整数 k。
    接下来一个长度不超过 105 的字符串 S。

    Output

    输出一行,表示字典序最小的“魔力串”。

    Sample Input

    13
    bcbcbacbbbbbabbacbcbacbbababaabbbaabacacbbbccaccbcaabcacbacbcabaacbccbbcbcbacccbcccbbcaacabacaaaaaba

    Sample Output

    cbc

    HINT

    S的长度<=100000

    思路{

      欲求max(min),有二分答案的排名k,排名越大,越容易满足要求,越小则越难,满足单调性。

      由之前套路可得:所有的本质不同子串个数为∑n-sa[i]-height[i]

      可查找排名为k的串,然后从后面开始枚举子串,比较答案串和当前串,若当前串较大,是不能让他出现的,切一段,更新串的右端点。判断切多少次.基于此二分。

      !:RMQ处理LCP细节!

    }

     1 #include<map>
     2 #include<set>
     3 #include<list>
     4 #include<deque>
     5 #include<cmath>
     6 #include<queue>
     7 #include<stack>
     8 #include<vector>
     9 #include<cstdio>
    10 #include<complex>
    11 #include<cstring>
    12 #include<cstdlib>
    13 #include<iostream>
    14 #include<algorithm>
    15 #define maxx 100010
    16 #define RG register
    17 #define LL long long
    18 #define db double
    19 using namespace std;
    20 int sa[maxx],X[maxx],rnk[maxx],Y[maxx],height[maxx],dp[maxx][69],tong[maxx];char s[maxx];
    21 bool comp(int *r,int a,int b,int len){return r[a]==r[b]&&r[a+len]==r[b+len];}
    22 void build_sa(int n){
    23   int *x=X,*y=Y,*t,Max=3000;
    24   for(int i=0;i<=Max;++i)tong[i]=0;
    25   for(int i=0;i<n;++i)tong[x[i]=s[i]]++;
    26   for(int i=0;i<Max;++i)tong[i]+=tong[i-1];
    27   for(int i=n-1;i!=-1;i--)sa[--tong[x[i]]]=i;
    28   for(int j=1,p=0,i;p<n;Max=p,j<<=1){
    29     for(i=n-1,p=0;i>=n-j;--i)y[p++]=i;
    30     for(i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
    31     for(i=0;i<=Max;++i)tong[i]=0;
    32     for(i=0;i<n;++i)tong[x[y[i]]]++;
    33     for(i=0;i<=Max;++i)tong[i]+=tong[i-1];
    34     for(i=n-1;i!=-1;i--)sa[--tong[x[y[i]]]]=y[i];
    35     for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i)
    36       x[sa[i]]=comp(y,sa[i],sa[i-1],j)?p-1:p++;
    37   }
    38 }int n;
    39 void geth(){
    40   int i,j,k=0;
    41   for(i=1;i<=n;++i)rnk[sa[i]]=i;
    42   for(i=0;i<n;height[rnk[i++]]=k)
    43     for(k?k--:0,j=sa[rnk[i]-1];s[i+k]==s[j+k];k++);
    44 }
    45 void RMQ(){
    46   for(int i=1;i<=n;++i)dp[i][0]=height[i];
    47   for(int j=1;(1<<j)<=n;++j)
    48     for(int i=1;i+(1<<(j-1))-1<=n;++i)
    49       dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    50 }
    51 LL LCP(int x,int y){
    52   if(x==y)return n-x+1; 
    53   x=rnk[x],y=rnk[y];if(x>y)swap(x,y);x++;
    54   int t=(int)(log(double(y-x+1))/log(2.000));
    55   return min(dp[x][t],dp[y-(1<<t)+1][t]);
    56 }
    57 bool comp(int l,int r,int L,int R){//L,R 答案,l,r当前子串 取最小
    58   int len=r-l+1,LEN=R-L+1,all=LCP(l,L);
    59   if(all>=LEN&&LEN<len)return true;
    60   if(all>=len&&LEN>=len)return false;
    61   if(all>=len&&all>=LEN)return LEN<len;
    62   return s[l+all]>s[L+all];
    63 }int L,R;
    64 void gett(LL kk){//得到第k小串位置
    65   LL sum=0;
    66   for(int i=1;i<=n;++i){
    67     sum=n-sa[i]-height[i];
    68     if(sum<kk)kk-=sum;
    69     else {L=sa[i],R=sa[i]+height[i]+kk-1;break;}
    70   }
    71 }int k;
    72 bool check(){
    73   int to=n-1,cnt=1;
    74   for(int i=n-1;i>=0;--i){
    75     if(s[i]>s[L])return false;
    76     if(comp(i,to,L,R))cnt++,to=i;
    77     if(cnt>k)return false;
    78   }return true;
    79 }
    80 int main(){
    81   //freopen("1.in","r",stdin);
    82   //freopen("1.out","w",stdout);
    83   scanf("%d",&k);
    84   scanf("%s",s);n=strlen(s),s[n]='0';
    85   build_sa(n+1),geth(),RMQ();
    86   LL l=1,r=0;
    87   for(int i=1;i<=n;++i)r+=n-sa[i]-height[i];
    88   while(l<=r){
    89     LL mid=(l+r)>>1;
    90     gett(mid);
    91     if(check())r=mid-1;
    92     else l=mid+1;
    93   }gett(r+1);for(int i=L;i<=R;++i)cout<<s[i];puts("");
    94   return 0;
    95 }
  • 相关阅读:
    JavaScript中出现这个statement expected
    java: 非法字符: 'ufeff' 需要class, interface或enum
    码云如何配置公钥
    Git命令
    配置git签名
    Scanner练习总结
    怎么将项目在Eclipse中生成doc文档
    java文件使用命令生成doc文档
    包机制总结
    变量和运算符总结
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6958842.html
Copyright © 2020-2023  润新知