题目: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. http 和 soap 关系 - 转载

    http soap关系 HTTP http:是一个客户端和服务器端请求和应答的标准(TCP).http协议其目的是为了提供一种发布和接收htttp页面的方法 一http协议的客户端与服务器的交互:由H ...

  2. Linux新手常用命令 - 转载

    开始→运行→cmd命令 集锦 cls------------命令窗清屏eqit-----------退出当前命令ping ip--------检查网络故障ipconfig-------查看IP地址wi ...

  3. Java 正则表达式 Pattern & Matcher

    通常会有这种需求: 在文档中搜索有规律的字符串,然后进行统计或者替换.Java.util.regex包下的Pattern和Matcher这两个类提供了通过正则表达式来匹配查询,甚至替换的功能.那么我们 ...

  4. 【LABVIEW到C#】4》String的操作之Search and Replace.vi

    C#封装如下: public class SearchAndRepalce : Darrenstring { public bool replaced; private string stringou ...

  5. Selenium with Python 001 - 安装篇

    Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试. 通过Selenium Python的API,你可以非常直观 ...

  6. jmeter导入jar包后在beanshell中import失效的问题解决

    最近一直很忙,没有时间来更新了,今天抽空把之前遇到的问题记录下来. 之前在使用jmeter做http请求性能压测时,因为要对所有入参做排序再加密作为一个入参,所以写了一段java代码,用来处理入参,打 ...

  7. ICE 中后台开发

    1.https://alibaba.github.io/ice/#/block 2.https://www.zhihu.com/question/266529857/answer/309604282 ...

  8. Device Drivers Should Not Do Power Management

    有人对现有的电源管理提出了意见,认为驱动程序不应该做电源管理,paper地址在这里: http://www.ruf.rice.edu/~mobile/publications/xu2014apsys. ...

  9. 【第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛-J】 强迫症的序列

    小A是一个中度强迫症患者,每次做数组有关的题目都异常难受,他十分希望数组的每一个元素都一样大,这样子看起来才是最棒的,所以他决定通过一些操作把这个变成一个看起来不难受的数组,但他又想不要和之前的那个数 ...

  10. String、StringBuffer、StringBuilder分析(jdk8)

    以下代码只挑选了关键方法进行分析 public final class String //String类不可继承,实现了序列化 implements java.io.Serializable, Com ...