博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4310 : 跳蚤
阅读量:5253 次
发布时间:2019-06-14

本文共 1313 字,大约阅读时间需要 4 分钟。

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

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

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

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

 

#include
#include
#include
#define N 100010using 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-1)break; } for(j=rk[height[i=k=0]=0];i
y)swap(x,y); int k=Log[y-x]; return min(f[k][x+1],f[k][y-(1<
=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<
<=n;i++)f[j][i]=min(f[j-1][i],f[j-1][i+(1<
>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;}

  

转载于:https://www.cnblogs.com/clrs97/p/5119087.html

你可能感兴趣的文章
编程算法 - 左旋转字符串 代码(C)
查看>>
IOS解析XML
查看>>
Python3多线程爬取meizitu的图片
查看>>
树状数组及其他特别简单的扩展
查看>>
zookeeper适用场景:分布式锁实现
查看>>
110104_LC-Display(液晶显示屏)
查看>>
httpd_Vhosts文件的配置
查看>>
php学习笔记
查看>>
普通求素数和线性筛素数
查看>>
PHP截取中英文混合字符
查看>>
【洛谷P1816 忠诚】线段树
查看>>
电子眼抓拍大解密
查看>>
poj 1331 Multiply
查看>>
tomcat7的数据库连接池tomcatjdbc的25个优势
查看>>
Html 小插件5 百度搜索代码2
查看>>
P1107 最大整数
查看>>
多进程与多线程的区别
查看>>
Ubuntu(虚拟机)下安装Qt5.5.1
查看>>
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
查看>>
java 常用命令
查看>>