题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4310

答案有单调性?

二分出来一个子串,判断的时候需要满足那些字典序比它大的子串都不出现!

原来想的是在 sa[ ] 上二分找到最右端 j ,满足自己到 j 之间的位置与自己的 LCP >= ans_len ;然后从前往后遍历,如果走到一个位置 k 发现它的 sa[ ] 是在那个 LCP >= ans_len 的区间内的,则需要把它截断;可以在 k ~ k+ans_len-1 之间选一个位置(在该位置后面截断);如果这段区间里没有之前弄出来的截断的话,就贪心地在最靠后放一个。

但这样不能让所有字典序比自己大的子串都不出现。

看看题解,原来是从后往前,一边通过 rk[ ] 来判断这个位置需不需要截断。要截断的话,范围就是当前位置 k 到 k + min( LCP , ans_len ) ;贪心就是如果还没被截断的话就在 k+1 位置截开。注意 LCP == 0 的话这个二分值一定不是答案,因为长度为1的子串不能被截开了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+,K=;
int n,a[N],sa[N],rk[N],tp[N],tx[N],ht[N][K],lg[N],bin[K];
ll sm[N];char s[N];
int Mn(int a,int b){return a<b?a:b;}
void Rsort(int n,int nm)
{
for(int i=;i<=nm;i++)tx[i]=;
for(int i=;i<=n;i++)tx[rk[i]]++;
for(int i=;i<=nm;i++)tx[i]+=tx[i-];
for(int i=n;i;i--)sa[tx[rk[tp[i]]]--]=tp[i];
}
void get_sa(int n,int nm)
{
for(int i=;i<=n;i++)tp[i]=i,rk[i]=a[i];
Rsort(n,nm);
for(int k=;k<=n;k<<=)
{
int tot=;
for(int i=n-k+;i<=n;i++)tp[++tot]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++tot]=sa[i]-k;
Rsort(n,nm);memcpy(tp,rk,sizeof rk);nm=;rk[sa[]]=;
for(int i=,u,v;i<=n;i++)
{
u=sa[i]+k;v=sa[i-]+k;if(u>n)u=;if(v>n)v=;
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[u]==tp[v])?nm:++nm;
}
if(nm==n)break;
}
}
void get_ht(int n)
{
lg[]=;for(int i=;i<=n;i++)lg[i]=lg[i>>]+;//i=2
bin[]=;for(int i=;i<=lg[n];i++)bin[i]=bin[i-]<<;
for(int i=,k=,j;i<=n;i++)
{
for(k?k--:,j=sa[rk[i]-];i+k<=n&&j+k<=n&&s[i+k]==s[j+k];k++);
ht[rk[i]][]=k;
}
for(int j=;j<=lg[n];j++)
for(int i=;i+bin[j]-<=n;i++)
ht[i][j]=Mn(ht[i][j-],ht[i+bin[j-]][j-]);
}
void fnd(ll x,int &id,int &len)
{
int l=,r=n;
while(l<=r)
{
int mid=l+r>>;
if(sm[mid]>=x)id=mid,r=mid-;
else l=mid+;
}
len=n-sa[id]+-(sm[id]-x);
}
int get_lcp(int l,int r)
{
if(l==r)return n-l+;
l=rk[l]; r=rk[r]; if(l>r)swap(l,r);
int d=lg[r-l];
return Mn(ht[l+][d],ht[r-bin[d]+][d]);//l+1
}
int chk(int id,int len)
{
int cnt=,lst=n+;
for(int i=n;i;i--)
{
if(rk[i]<id)continue;
int d=Mn(get_lcp(i,sa[id]),len);//Mn
if(!d)return K;
if(lst<=i+d)continue;
cnt++; lst=i+;
}
return cnt;
}
int main()
{
int lm;scanf("%d",&lm);lm--;
scanf("%s",s+);n=strlen(s+);
for(int i=;i<=n;i++)tp[i]=(int)s[i];
sort(tp+,tp+n+); int m=unique(tp+,tp+n+)-tp-;
for(int i=;i<=n;i++)a[i]=lower_bound(tp+,tp+m+,(int)s[i])-tp;
get_sa(n,m); get_ht(n);
for(int i=;i<=n;i++)sm[i]=sm[i-]+(n-sa[i]+)-ht[i][];
ll l=,r=sm[n]; int id,len,pid,plen;
while(l<=r)
{
ll mid=l+r>>;fnd(mid,id,len);
if(chk(id,len)<=lm)pid=id,plen=len,r=mid-;
else l=mid+;
}
for(int i=sa[pid],j=;j<=plen;i++,j++)putchar(s[i]);puts("");
return ;
}

bzoj 4310 跳蚤——后缀数组+二分答案+贪心的更多相关文章

  1. bzoj 4310 跳蚤 —— 后缀数组+二分答案+贪心

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4310 二分答案——在本质不同的子串中二分答案! 如果二分到的子串位置是 st,考虑何时必须分 ...

  2. BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单 ...

  3. Poj 1743 Musical Theme(后缀数组+二分答案)

    Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...

  4. Poj 3261 Milk Patterns(后缀数组+二分答案)

    Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...

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

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

  6. 跳蚤[BZOJ4310](后缀数组+二分答案传判定)

    不知道后缀数组的请退回去! 题面: 题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究.首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S ...

  7. BZOJ 4556: [Tjoi2016&Heoi2016]字符串(后缀数组 + 二分答案 + 主席树 + ST表 or 后缀数组 + 暴力)

    题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s ...

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

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

  9. POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串

                                                                              Life Forms Time Limit: 500 ...

随机推荐

  1. [BZOJ2717]迷路的兔子[构造]

    构造题…当然需要推(看)一推(看)规(题)律(解)啦... 其实是在Discuss那个CA的一句话题解里面翻到这个东西的... 用奇怪的姿势枚举一下...先贴代码 #include<bits/s ...

  2. 关于使用JAVA正则表达式报java.lang.StackOverflowError错误问题

    最近在使用hadoop做apache日志分析,发现测试数据没问题,但数据一多就出问题,报 java.lang.StackOverflowError错误,最后定位为正则表达式栈溢出,发现某些行的日志数据 ...

  3. selenium学习笔记(webdriver下载配置)

    selenium安装后默认安装firefox可以直接使用,当然可以通过其它浏览器 博主这里整理了:chrome . IE 首先是下载地址 http://docs.seleniumhq.org/down ...

  4. spirng: srping mvc配置(访问路径配置)搭建SpringMVC——最小化配置

    搭建SpringMVC——最小化配置 最开始接触网页的时候,是纯的html/css页面,那个时候还是用Dreamweaver来绘制页面. 随着网站开发的深入,开始学习servlet开发,记得最痛苦的就 ...

  5. 分享知识-快乐自己:Ajax 跨域请求处理

    <%-- Created by IntelliJ IDEA. User: asus Date: 2019/1/24 Time: 15:57 To change this template use ...

  6. docker mysql 8.0

    Pull library/mysql $ docker pull mysql Load image $ docker load -i mysql.tar Save image $ docker sav ...

  7. Python中的import,from...import以及模块、包、库的概念

    首先,说明一下,我使用的是python3.6.3win32版本,使用的IDE是pycharm2017社区免费版. 刚开始接触python编程不久,有很多概念都不是特别清楚,但是我觉得既然选择,尽自己最 ...

  8. day5-time & datetime模块

    1.概述 程序设计开发过程中,往往存在很多场景,需要把时间和日期以某种特定形式格式化输出,在python中我们需要借助time & datetime模块来实现,今天就来一探这两大模块的究竟. ...

  9. 解决loadrunner在脚本回放时长时间等待及在vugen中create controller scenario时报错的方法!超管用!!

    解决loadrunner在脚本回放时长时间等待及在vugen中create controller scenario时报错的方法 经过咨询,有两种方法.经过实践,下面的方法1有效,方法2无效(我下载安装 ...

  10. 深入理解c/c++ 内存对齐

    内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐.原因在于,为了访问未对齐的内存,处理器需要作两次内存访问:然而,对齐的内存访问仅需要一 ...