注意到答案一定是原串的子串,于是考虑造出SA,二分答案是第几小的子串。第k小子串很容易在SA上求出。之后计算使他成为最大子串至少要在几个位置切割,对每个字典序比答案大的后缀,找到所有合法切割位置(求lcp即可),就转化成了选最少的点使每个区间都包含至少一个点的经典问题。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 100010
#define ll long long
int n,m,sa[N],sa2[N],rk[N<<],tmp[N<<],h[N],cnt[N],l[N];
char s[N];
ll tot=;
void make()
{
int m=;
for (int i=;i<=n;i++) cnt[rk[i]=s[i]]++,m=max(m,(int)s[i]);
for (int i=;i<=m;i++) cnt[i]+=cnt[i-];
for (int i=n;i>=;i--) sa[cnt[rk[i]]--]=i;
for (int k=;k<=n;k<<=)
{
int p=;
for (int i=n-k+;i<=n;i++) sa2[++p]=i;
for (int i=;i<=n;i++) if (sa[i]>k) sa2[++p]=sa[i]-k;
memset(cnt,,sizeof(cnt));
for (int i=;i<=n;i++) cnt[rk[i]]++;
for (int i=;i<=m;i++) cnt[i]+=cnt[i-];
for (int i=n;i>=;i--) sa[cnt[rk[sa2[i]]]--]=sa2[i];
memcpy(tmp,rk,sizeof(rk));
p=rk[sa[]]=;
for (int i=;i<=n;i++)
{
if (tmp[sa[i]]!=tmp[sa[i-]]||tmp[sa[i]+k]!=tmp[sa[i-]+k]) p++;
rk[sa[i]]=p;
}
if (p==n) break;
m=p;
}
for (int i=;i<=n;i++)
{
h[i]=max(h[i-]-,);
while (s[i+h[i]]==s[sa[rk[i]-]+h[i]]) h[i]++;
}
}
bool check(ll k)
{
int x=;
for (int i=;i<=n;i++)
if (k<=n-sa[i]+-h[sa[i]]) {x=i;break;}
else k-=n-sa[i]+-h[sa[i]];
k+=h[sa[x]];memset(l,,sizeof(l));
int lcp=k;if (k<n-sa[x]+) l[sa[x]+lcp-]=max(l[sa[x]+lcp-],sa[x]);
for (int i=x+;i<=n;i++)
{
lcp=min(lcp,h[sa[i]]);
if (!lcp) return ;
l[sa[i]+lcp-]=max(l[sa[i]+lcp-],sa[i]);
}
int t=;
for (int i=;i<=n;i++)
if (l[i])
{
t++;if (t>m) return ;
int x=i;while (x<n&&l[x+]<=i) x++;
i=x;
}
return ;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4310.in","r",stdin);
freopen("bzoj4310.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
m=read();
scanf("%s",s+);n=strlen(s+);
make();
tot=1ll*n*(n+)>>;
for (int i=;i<=n;i++) tot-=h[i];
ll l=,r=tot,ans;
while (l<=r)
{
ll mid=l+r>>;
if (check(mid)) r=mid-,ans=mid;
else l=mid+;
}
for (int i=;i<=n;i++)
if (ans<=n-sa[i]+-h[sa[i]]) {for (int j=sa[i];ans+h[sa[i]]>;j++,ans--)printf("%c",s[j]);break;}
else ans-=n-sa[i]+-h[sa[i]];
return ;
}

BZOJ4310 跳蚤(后缀数组+二分答案)的更多相关文章

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

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

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

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

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4310 答案有单调性? 二分出来一个子串,判断的时候需要满足那些字典序比它大的子串都不出现! ...

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

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

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

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

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

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

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

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

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

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

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

                                                                              Life Forms Time Limit: 500 ...

随机推荐

  1. Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token

    原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf?   因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...

  2. TableView滑动时候出现的卡顿现象

    分析 UITableView是UIScrollView的子类,因此它可以自动响应滚动事件(一般为上下滚动).  它内部包含0到多个UITableViewCell对象,每个table cell展示各自的 ...

  3. 11、Java并发编程:并发容器之CopyOnWriteArrayList

    Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...

  4. linux-centos6②

  5. 汽车VIN码,车架号,移动端,服务器端OCR识别 技术公司

    很多人在购买车辆的时候,只关注性能.外观.内饰等,其实真正的内行是首先看车辆的VIN码,也叫车架号码. VIN码(车架号码)是一辆车的唯一身份证明,一般在车辆的挡风玻璃处,有的在车辆防火墙上,或B柱铭 ...

  6. selenium自动化测试资源整理

    1. 所有版本chrome下载 是不是很难找到老版本的chrome?博主收集了几个下载chrome老版本的网站,其中哪个下载的是原版的就不得而知了. http://www.slimjet.com/ch ...

  7. 在几份docx文档中里查找某个值

    import docx, os def readDocx(fileName): doc = docx.Document(fileName) content = '\n'.join([para.text ...

  8. C++clock()延时循环

    函数clock(),返回程序开始执行后所用的系统时间,但是有两个复制问题. 1.clock()返回时间的单位不一定是秒 2.该函数的返回类型在某些系统上可能是Long,也可能是unsigned lon ...

  9. eos智能合约开发最佳实践

    安全问题 1.可能的错误 智能合约终止 限制转账限额 限制速率 有效途径来进行bug修复和提升 2.谨慎发布智能合约 对智能合约进行彻底的测试 并在任何新的攻击手法被发现后及时制止 赏金计划和审计合约 ...

  10. js如何处理字符串中带有↵字符

    js或vue中如何处理字符串中带有↵字符 split('\n') 使用split('\n')将字符串分割成数组就行 如果我们在vue中,只需要在页面中绑定变量时操作split('\n')就可以了: & ...