首先求出后缀数组,得到本质不同的子串的个数。

然后二分答案,每次先通过后缀数组求出第$mid$小的子串,然后贪心进行检验。

检验的时候,从后往前贪心,每次加入一个后缀,如果不能加了,那就划为一段。

时间复杂度$O(n\log n)$。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
typedef long long ll;
char s[N];
int K,n,i,j,rk[N],sa[N],height[N],tmp[N],cnt[N],Log[N],f[16][N],g[N];
ll L=1,R,mid;
int len,nowl,nowr,ansl,ansr;
void suffixarray(int n,int m){
int i,j,k;n++;
for(i=0;i<n;i++)cnt[rk[i]=s[i]]++;
for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
for(i=0;i<n;i++)sa[--cnt[rk[i]]]=i;
for(k=1;k<=n;k<<=1){
for(i=0;i<n;i++){
j=sa[i]-k;
if(j<0)j+=n;
tmp[cnt[rk[j]]++]=j;
}
sa[tmp[cnt[0]=0]]=j=0;
for(i=1;i<n;i++){
if(rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k])cnt[++j]=i;
sa[tmp[i]]=j;
}
memcpy(rk,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if(j>=n-1)break;
}
for(j=rk[height[i=k=0]=0];i<n-1;i++,k++)
while(~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rk[sa[j]+1];
}
inline int lcp(int x,int y){
if(x==y)return n-x;
x=rk[x],y=rk[y];
if(x>y)swap(x,y);
int k=Log[y-x];
return min(f[k][x+1],f[k][y-(1<<k)+1]);
}
void kth(ll k){
ll s=0;
for(int i=1;i<=n;s+=n-sa[i]-height[i],i++)if(s+n-sa[i]-height[i]>=k){
nowl=sa[i],nowr=nowl+height[i]+k-s-1;
len=nowr-nowl+1;
return;
}
}
inline bool ask(int l,int r){
int t=min(lcp(l,nowl),min(r-l+1,len));
if(t==r-l+1&&t<=len)return 1;
if(t==len)return 0;
return s[l+t]<=s[nowl+t];
}
bool check(){
int i,j,k=0;
for(i=n-1;~i;i=j,k++){
for(j=i;~j;j--)if(!ask(j,i))break;
if(j==i)return 0;
}
return k<=K;
}
int main(){
scanf("%d%s",&K,s);
n=strlen(s);
suffixarray(n,128);
for(i=2;i<=n;i++)Log[i]=Log[i>>1]+1;
for(i=1;i<=n;i++)f[0][i]=height[i];
for(j=1;j<17;j++)for(i=1;i+(1<<j-1)<=n;i++)f[j][i]=min(f[j-1][i],f[j-1][i+(1<<j-1)]);
for(i=1;i<=n;i++)R+=n-sa[i]-height[i];
while(L<=R){
kth(mid=(L+R)>>1);
if(check())ansl=nowl,ansr=nowr,R=mid-1;else L=mid+1;
}
for(i=ansl;i<=ansr;i++)putchar(s[i]);
return 0;
}

  

BZOJ4310 : 跳蚤的更多相关文章

  1. [BZOJ4310] 跳蚤 - 后缀数组,二分,ST表

    [BZOJ4310] 跳蚤 Description 首先,他会把串分成不超过 \(k\) 个子串,然后对于每个子串 \(S\) ,他会从 \(S\) 的所有子串中选择字典序最大的那一个,并在选出来的 ...

  2. BZOJ4310: 跳蚤 【后缀数组+二分】

    Description 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究.首先,他会把串 分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典 ...

  3. BZOJ4310 跳蚤(后缀数组+二分答案)

    注意到答案一定是原串的子串,于是考虑造出SA,二分答案是第几小的子串.第k小子串很容易在SA上求出.之后计算使他成为最大子串至少要在几个位置切割,对每个字典序比答案大的后缀,找到所有合法切割位置(求l ...

  4. [BZOJ4310] 跳蚤 SAM || SA

    没有代码的. 传送门 先二分出第 \(mid\) 大的字串 \(s\),然后从后往前切割,每次大于 \(s\) 了就不行. 涉及到的操作:求第 \(mid\) 大子串:比较两个字串(求 \(lcp\) ...

  5. 【算法】后缀自动机(SAM) 例题

    算法介绍见:http://www.cnblogs.com/Sakits/p/8232402.html 广义SAM资料:https://www.cnblogs.com/phile/p/4511571.h ...

  6. 【STACK】Several待填的坑

    待学的习: https://www.cnblogs.com/xiao-ju-ruo-xjr/p/9149792.html 待写的题: loj#3184:「CEOI2018」斐波那契表示法 luoguP ...

  7. 【BZOJ4310】跳蚤

    [BZOJ4310]跳蚤 Description 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他 ...

  8. 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分

    4310: 跳蚤 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 180  Solved: 83[Submit][Status][Discuss] De ...

  9. 【bzoj4310】跳蚤 后缀数组+二分

    题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...

随机推荐

  1. MFC 最大化 的时候控件 按比例变大

    在dlg类头文件中声明CPoint Old; 在BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()声明一个映射:ON_WM_SIZE() 这样以后就可以在M_SIZE事件的时候 ...

  2. 题目1006:ZOJ问题

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:13212 解决:2214 题目描述: 对给定的字符串(只包含'z','o','j'三种字符),判断他是否能AC. 是否AC的规则如下:1. ...

  3. RAID阵列的初始化与管理

    如果我们创建RAID阵列的目的是新部署一台服务器,我们建议所有新创建的RAID阵列都应该做初始化操作,这样,硬盘上原有的用户数据将被清除,以便进行后续的系统,软件安装. 转自: http://zh.c ...

  4. macbook air电池保养方法

    转自: http://bbs.feng.com/read-htm-tid-5819895.html http://www.zhihu.com/question/22628030

  5. 90天打造日均在线网站1W+的友情链接平台

    导读:三个月过去了,好友张森终于把一款默默无名的软件打造出了日均1W+在线的平台,我认为成功的因素很简单,1,找准了用户群体的痛点;2,肯花精力做运营;3,合理的推广.本文是他的自述,打造一款产品,说 ...

  6. CodeForces - 405A

    Gravity Flip Time Limit: 1000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Submit ...

  7. 打开genesis时一直在等待,后出现Timeout in communication read解决方法

    运行输入:netsh winsock reset 然后重启电脑

  8. Dijkstra最短路算法

    Dijkstra最短路算法 --转自啊哈磊[坐在马桶上看算法]算法7:Dijkstra最短路算法 上节我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最 ...

  9. 在竞赛ACM Java处理输入输出

    一.Java之ACM注意点 1. 类名称必须采用public class Main方式命名 2. 在有些OJ系统上,即便是输出的末尾多了一个“ ”,程序可能会输出错误,所以在我看来好多OJ系统做的是非 ...

  10. Struts2 Action与Servlet API耦合

    单元测试在开发中是非常重要的一个环节程序员在写完代码时,相应的单元测试也应写完整,否则你的代码就是不能让人信服的Struts2将Action与Servlet的API进行解耦之后,就使得单元测试变得非常 ...