【bzoj4310/hdu5030-跳蚤】后缀数组
我真的是。。调了一百年。。
傻逼的人生。。
而且这题好像可以用sam做哎!我Y出了一个奇怪的办法。。
好吧sam是不能做这题的。搞错了。
说说后缀数组好了。。
搞后缀数组
然后我们要二分一个子串,判断是否有一种划分方法,满足划分出来的所有串的最大子串不超过这个串。
二分是第now个后缀
二分第now个多长的前缀
————确定了一个子串
首先,这题具有单调性,而且是求最大串最小,所以我们可以二分答案串。
怎么二分答案串呢,我们不是已经用后缀数组求出了sa数组吗,sa数组表示的串是排过序的,其中每个后缀的前缀子串大小按长度的递增而递增,所以可以在sa数组里面二分。(我是先二分后缀,再二分长度)然后是判断,怎么判断是不是可以划分成至多k个串使他们都不超过二分串。还是在sa上做。如果他的sa位置小于mid,那么不用管,因为它怎么样都是小于二分串的。如果他的sa位置大于等于mid,而且他跟二分串没有LCP,那么这个二分一定没有答案,因为最小二分都使他不符合。除此之外,求出sa位置大于等于mid的所有串跟二分串的LCP,在sa[i]~sa[i]+lcp-1的位置上一定要至少打一个标记,因为不打标记它就会比二分串大了。所以最后我们会得到很多个区间,在这些区间里面至多打k-1个标记,使得每个区间中有含有一个标记。转化成了这样,就很容易做了。貌似是smg区间覆盖之类的问题。排个序,去个重,判断+累加一下就可以了。
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<cmath>
- #include<iostream>
- #include<algorithm>
- using namespace std;
- const int N=,Inf=(int)1e9;
- int K,n,cl,ed,r[N],h[N],t[N],rk[N],Rs[N],sa[N],y[N],wr[N];
- char c[N];
- int minn(int x,int y){return x<y ? x:y;}
- void get_sa(int m)
- {
- for(int i=;i<=cl;i++) rk[i]=c[i]-'a'+;
- for(int i=;i<=m;i++) Rs[i]=;
- for(int i=;i<=cl;i++) Rs[rk[i]]++;
- for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
- for(int i=cl;i>=;i--) sa[Rs[rk[i]]--]=i;//debug
- int ln=,p=;
- while(p<cl)
- {
- int k=;
- for(int i=cl-ln+;i<=cl;i++) y[++k]=i;
- for(int i=;i<=cl;i++)
- if(sa[i]>ln) y[++k]=sa[i]-ln;
- for(int i=;i<=cl;i++) wr[i]=rk[y[i]];
- for(int i=;i<=m;i++) Rs[i]=;
- for(int i=;i<=cl;i++) Rs[wr[i]]++;
- for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
- for(int i=cl;i>=;i--) sa[Rs[wr[i]]--]=y[i];//debug
- for(int i=;i<=cl;i++) wr[i]=rk[i];
- for(int i=cl+;i<=cl+ln;i++) wr[i]=;
- rk[sa[]]=;
- p=;
- for(int i=;i<=cl;i++)
- {
- if(wr[sa[i]]!=wr[sa[i-]] || wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
- rk[sa[i]]=p;
- }
- ln*=;m=p;
- // for(int i=1;i<=cl;i++) printf("%d ",rk[i]);printf("\n");
- // for(int i=1;i<=cl;i++) printf("%d ",sa[i]);printf("\n");
- }
- sa[]=rk[]=;
- }
- void get_h()
- {
- int k=;
- for(int i=;i<=cl;i++) if(rk[i]!=)
- {
- int j=sa[rk[i]-];
- if(k) k--;
- while(c[i+k]==c[j+k] && i+k<=cl && j+k<=cl) k++;
- h[rk[i]]=k;
- }
- h[]=;
- }
- bool ok(int ll,int rr)
- {
- int k=rr-ll+;
- memset(t,,sizeof(t));
- memset(r,,sizeof(r));
- for(int i=rk[ll];i<=cl;i++)
- {
- if(i!=rk[ll]) k=minn(k,h[i]);
- else if(rr==cl) continue;
- if(k==) return ;
- if(t[sa[i]]== || sa[i]+k-<t[sa[i]]) t[sa[i]]=sa[i]+k-;
- }
- int pl=,pr=,cut,ans;
- for(int i=cl;i>=;i--)
- {
- if(!t[i]) continue;
- if(!pr) {pr=i;continue;}
- if(pr<=t[i]) t[i]=;
- pr=t[i];
- }
- for(int i=;i<=cl;i++) if(t[i]) r[t[i]]=i;
- pl=,pr=,cut=,ans=;
- for(int i=cl;i>=;i--)
- {
- if(!r[i]) continue;
- if(!pl) {pl=r[i],pr=i;cut=r[i];ans++;continue;}
- if(i<pl) cut=r[i],ans++;
- if(pl<=i && i<=pr)
- {
- if(!(cut>=r[i] && cut<=i)) cut=r[i],ans++;
- }
- pl=r[i],pr=i;
- }
- if(ans<=K-) return ;
- return ;
- }
- int check(int now)
- {
- int ll=sa[now]+h[now],rr=cl,mid;
- while(ll<=rr)
- {
- mid=(ll+rr)/;
- if(ok(sa[now],mid))
- {
- rr=mid;
- if(ll==rr) return ll;
- }
- else ll=mid+;
- }
- if(ll<=rr) return ll;
- return ;
- }
- int main()
- {
- // freopen("a.in","r",stdin);
- freopen("magic.in","r",stdin);
- freopen("magic.out","w",stdout);
- scanf("%d",&K);
- scanf("%s",c+);
- cl=strlen(c+);
- get_sa();
- get_h();
- int ll=,rr=cl,mid,now;
- while(ll<rr)
- {
- mid=(ll+rr)/;
- now=check(mid);
- if(now) rr=mid,ed=now;
- else ll=mid+;
- }
- if(ll)
- {
- for(int i=sa[ll];i<=ed;i++) printf("%c",c[i]);printf("\n");
- }
- return ;
- }
贴一下代码啦。
【bzoj4310/hdu5030-跳蚤】后缀数组的更多相关文章
- 【BZOJ-4310】跳蚤 后缀数组 + ST表 + 二分
4310: 跳蚤 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 180 Solved: 83[Submit][Status][Discuss] De ...
- 【bzoj4310】跳蚤 后缀数组+二分
题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...
- [BZOJ4310] 跳蚤 - 后缀数组,二分,ST表
[BZOJ4310] 跳蚤 Description 首先,他会把串分成不超过 \(k\) 个子串,然后对于每个子串 \(S\) ,他会从 \(S\) 的所有子串中选择字典序最大的那一个,并在选出来的 ...
- bzoj 4310 跳蚤 —— 后缀数组+二分答案+贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4310 二分答案——在本质不同的子串中二分答案! 如果二分到的子串位置是 st,考虑何时必须分 ...
- bzoj 4310 跳蚤——后缀数组+二分答案+贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4310 答案有单调性? 二分出来一个子串,判断的时候需要满足那些字典序比它大的子串都不出现! ...
- BZOJ4310: 跳蚤 【后缀数组+二分】
Description 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究.首先,他会把串 分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典 ...
- 跳蚤[BZOJ4310](后缀数组+二分答案传判定)
不知道后缀数组的请退回去! 题面: 题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究.首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S ...
- bzoj 4310 跳蚤 二分答案+后缀数组/后缀树
题目大意 给定\(k\)和长度\(\le10^5\)的串S 把串分成不超过\(k\)个子串,然后对于每个子串\(s\),他会从\(s\)的所有子串中选择字典序最大的那一个,并在选出来的\(k\)个子串 ...
- 后缀数组 hash求LCP BZOJ 4310: 跳蚤
后缀数组的题博客里没放进去过..所以挖了一题写写 充实下博客 顺便留作板子.. 一个字符串S中 内容不同的子串 有 sigma{n-sa[i]+1-h[i]} (噢 这里的h[]就是大家熟知的he ...
随机推荐
- 你真的了解React吗
https://zhufengzhufeng.github.io/zhufengreact/index.html#t21.%E4%BB%80%E4%B9%88%E6%98%AFReact?
- 云计算之路-阿里云上:受够了OCS,改用ECS+Couchbase跑缓存
当今天早上在日志中发现这样的错误之后,对阿里云OCS(mecached缓存服务)的积怨倾泻而出. 2014-06-08 07:15:56,078 [ERROR] Enyim.Caching.Memca ...
- jmeter更改启动编码设置
项目中碰到这样的问题,在eclipse经过utf-8转码的代码,能正常运行,放到了jmeter里面运行,就是乱码,如下: String s = "乔佳飞"; String ss = ...
- Python升级3.6 强力Django+Xadmin打造在线教育平台
第 1 章 课程介绍 1-1 项目演示和课程介绍: 第 2 章 Windows下搭建开发环境 2-1 Pycharm.Navicat和Python解释器的安装: Pycharmhttp://www.j ...
- 容器基础(三): 使用Cgroups进行资源限制
Linux Cgroups Linux Cgroups 是 Linux 内核中用来为进程设置资源限制的一个重要功能. Cgroups将进程进行分组, 然后对这一组进程进行统一的资源监控和限制.Cgro ...
- 多文件上传 input 的multiple 属性
一.上传多张图片并且预览 HTML: <div class="container"> <label>请选择一个图像文件:</label> < ...
- 面试题中经常遇到的SQL题:删除重复数据,保留其中一条
如题,解决思路如下: 1.首先我们需要找出拥有重复数据的记录 ---以name字段分组 select Name,COUNT(Name) as [count] from Permission group ...
- 【python爬虫】对喜马拉雅上一个专辑的音频进行爬取并保存到本地
>>>内容基本框架: 1.爬虫目的 2.爬取过程 3.代码实现 4.爬取结果 >>>实验环境: python3.6版本,pycharm,电脑可上网. [一 爬虫目 ...
- 延迟加载(Lazyload)三种实现方式
定义:延迟加载也称为惰性加载,即在长网页中延迟加载图像.用户滚动到它们之前,视口外的图像不会加载.这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快.在某些情况下,它还可以帮助减少服务器负载. ...
- 安装elasticsearch-1.7.1及中文IK和近义词配置
安装elasticsearch及中文IK和近义词配置 https://www.cnblogs.com/yjf512/p/4789239.html 安装elasticsearch及中文IK和近义词配置 ...