• [BZOJ 4310]跳蚤


    [BZOJ 4310]跳蚤

    题目

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

    INPUT

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

    OUTPUT

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

    SAMPLE

    INPUT

    13
    bcbcbacbbbbbabbacbcbacbbababaabbbaabacacbbbccaccbcaabcacbacbcabaacbccbbcbcbacccbcccbbcaacabacaaaaaba

    OUTPUT

    cbc

    解题报告

    BZOJ上榜留念2333(我TM打了一个下午)

    首先我们看到题目要求的是最大值最小,那么我们考虑二分

    我们很容易知道,所有本质不同的字串数为$sum_{i}^{len}len-sa[i]-height[i]$

    (这个很容易由SA与height的含义推得,这里就不再展开证明了)

    那么我们二分第$mid$个字串,去判断这个字串是否满足条件

    判断就很好判断了(虽然我TM就是在这调了一下午),我们利用贪心的思想,从后向前枚举,然后判断是否要分开,最后判断分开次数与$k$的关系即可

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 using namespace std;
      6 char s[100005];
      7 int n,m;
      8 int t1[100005],t2[100005],t3[100005],buc[100005];
      9 int sa[100005],rank[100005],height[100005];
     10 inline void Suffix(){
     11     int i,j,k(0),p(0),*x(t1),*y(t2),*t;
     12     for(i=0;i<=m;++i)buc[i]=0;
     13     for(i=1;i<=n;++i)++buc[x[i]=s[i]];
     14     for(i=1;i<=m;++i)buc[i]+=buc[i-1];
     15     for(i=n;i>=1;--i)sa[buc[x[i]]--]=i;
     16     for(j=1;p<n;j<<=1,m=p){
     17         for(p=0,i=n-j+1;i<=n;++i)y[++p]=i;
     18         for(i=1;i<=n;++i)
     19             if(sa[i]>j)
     20                 y[++p]=sa[i]-j;
     21         for(i=0;i<=m;++i)buc[i]=0;
     22         for(i=1;i<=n;++i)t3[i]=x[y[i]];
     23         for(i=1;i<=n;++i)++buc[t3[i]];
     24         for(i=1;i<=m;++i)buc[i]+=buc[i-1];
     25         for(i=n;i>=1;--i)sa[buc[t3[i]]--]=y[i];
     26         for(t=x,x=y,y=t,x[sa[1]]=1,p=1,i=2;i<=n;++i)
     27             x[sa[i]]=((y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+j]==y[sa[i-1]+j]))?p:++p;
     28     }
     29     for(i=1;i<=n;++i)rank[sa[i]]=i;
     30     for(i=1;i<=n;height[rank[i++]]=k)
     31         for(k?--k:0,j=sa[rank[i]-1];s[i+k]==s[j+k];++k);
     32 }
     33 int k;
     34 typedef long long L;
     35 L tot;
     36 int ansl,ansr,ll,rr;
     37 /*inline void get_kth(L x){
     38     for(int i=1;i<=n;++i){
     39         if(x>(L)(n-sa[i]-height[i]+1))
     40             x-=(L)(n-sa[i]-height[i]+1);
     41         else{
     42             ll=sa[i],rr=sa[i]+height[i]+k-1;
     43             return;
     44         }
     45     }
     46 }*/
     47 inline bool cmp(int l,int r){
     48     for(int i=l,j=ll;i<=r&&j<=rr;++i,++j){
     49         if(s[i]<s[j])
     50             return true;
     51         if(s[i]>s[j])
     52             return false;
     53     }
     54 //  cout<<l<<' '<<r<<' '<<ll<<' '<<rr<<endl;
     55     if(rr-ll<r-l)
     56         return false;
     57     return true;
     58 }
     59 inline bool check(){
     60     int i,j,cnt(0);
     61     for(i=n;i>=1;i=j,++cnt){
     62         for(j=i;j>0;--j)
     63             if(!cmp(j,i))
     64                 break;
     65         if(i==j)
     66             return false;
     67     }
     68     return cnt<=k;
     69 }
     70 L sum[100005];
     71 int main(){
     72     scanf("%d%s",&k,s+1);
     73     n=strlen(s+1);
     74     m=130;
     75     Suffix();
     76     tot=n;
     77     for(int i=1;i<=n;++i){
     78         sum[i]=n-sa[i]+1-height[i];
     79         sum[i]+=sum[i-1];
     80         tot+=n-sa[i]-height[i];
     81     }
     82     L l(0),r(tot);
     83     while(l<=r){
     84         L mid((l+r)>>1);
     85 //      cout<<l<<' '<<r<<" "<<mid<<endl;
     86 //      get_kth(mid);
     87         L tmp(lower_bound(sum+1,sum+n+1,mid)-sum);
     88         ll=sa[tmp],rr=mid-sum[tmp-1]+sa[tmp]+height[tmp]-1;
     89 //      cout<<ll<<' '<<rr<<' '<<mid<<endl;
     90         if(check()){
     91             ansl=ll,ansr=rr;
     92             r=mid-1;
     93         }
     94         else
     95             l=mid+1;
     96     }
     97 //  cout<<ansl<<' '<<ansr<<endl;
     98     for(int i=ansl;i<=ansr;++i)
     99         putchar(s[i]);
    100 }
    View Code
  • 相关阅读:
    C#的注释
    为知笔记发布到博客,css设置
    eclipse创建springboot项目的三种方法
    创建maven父项目以及子项目
    C# 快捷键(总结)
    idea 项目转 eclipse项目
    freemarker常见语法大全
    Spring Boot Freemarker特别篇之contextPath【从零开始学Spring Boot
    Spring mvc请求处理流程详解(一)之视图解析
    React+SpringBoot项目部署
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7576144.html
Copyright © 2020-2023  润新知