2016vijos 1-1 兔子的字符串(后缀数组 + 二分 + 哈希)
题意:
给出一个字符串,至多将其划分为n部分,每一部分取出字典序最大的子串ci,最小化 最大的ci
先看一个简化版的问题:
给一个串s,再给一个s的子串t,问能否通过将串划分为k个部分,使t成为划分后的s的字典序最大子串
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- #define N 100001
- typedef long long LL;
- const int base=;
- int n,m;
- char s[N];
- int a[N];
- int v[N];
- int p,q=,k;
- int sa[][N],rk[][N];
- int h[N];
- unsigned long long Pow[N],has[N];
- pair<int,int>interval[N];
- void mul(int *sa,int*rk,int *SA,int *RK)
- {
- for(int i=;i<=n;++i) v[rk[sa[i]]]=i;
- for(int i=n;i;--i) if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;
- for(int i=n-k+;i<=n;++i) SA[v[rk[i]]--]=i;
- for(int i=;i<=n;++i) RK[SA[i]]=RK[SA[i-]]+(rk[SA[i]]!=rk[SA[i-]] || rk[SA[i]+k]!=rk[SA[i-]+k]);
- }
- void presa()
- {
- for(int i=;i<=n;++i) v[a[i]]++;
- for(int i=;i<=;++i) v[i]+=v[i-];
- for(int i=;i<=n;++i) sa[p][v[a[i]]--]=i;
- for(int i=;i<=n;++i) rk[p][sa[p][i]]=rk[p][sa[p][i-]]+(a[sa[p][i]]!=a[sa[p][i-]]);
- for(k=;k<n;k<<=,swap(p,q)) mul(sa[p],rk[p],sa[q],rk[q]);
- }
- void get_height()
- {
- int j,k=;
- for(int i=;i<=n;++i)
- {
- j=sa[p][rk[p][i]-];
- while(a[i+k]==a[j+k]) k++;
- h[rk[p][i]]=k;
- if(k) k--;
- }
- }
- void prehash()
- {
- Pow[]=;
- for(int i=;i<=n;++i) Pow[i]=Pow[i-]*base;
- for(int i=;i<=n;++i) has[i]=has[i-]*base+a[i];
- }
- pair<int,int>select(LL k)
- {
- int now;
- LL sum=;
- int l,r;
- for(int i=;i<=n;++i)
- {
- now=interval[i].second-interval[i].first+;
- if(sum+now>=k)
- {
- l=sa[p][i];
- r=interval[i].first+k-sum-;
- return make_pair(l,r);
- }
- sum+=now;
- }
- }
- unsigned long long get_hash(int l,int r)
- {
- return has[r]-has[l-]*Pow[r-l+];
- }
- int cmp(pair<int,int>x,pair<int,int>y)
- {
- if(get_hash(x.first,x.second)==get_hash(y.first,y.second)) return ;
- int Lx=x.second-x.first+,Ly=y.second-y.first+;
- int l=,r=min(Lx,Ly),mid,tmp=;
- while(l<=r)
- {
- mid=l+r>>;
- if(get_hash(x.first,x.first+mid-)==get_hash(y.first,y.first+mid-)) tmp=mid,l=mid+;
- else r=mid-;
- }
- if(tmp<min(Lx,Ly)) return s[x.first+tmp]<s[y.first+tmp] ? - : ;
- return Lx<Ly ? - : ;
- }
- bool check(pair<int,int>now)
- {
- int l=n,r=n,sum=;
- while(l>=)
- if(cmp(make_pair(l,r),now)==)
- {
- if(l==r) return false;
- r=l;
- sum++;
- if(sum>m) return false;
- }
- else l--;
- return true;
- }
- void solve()
- {
- LL l=,r=;
- for(int i=;i<=n;++i)
- {
- interval[i].first=sa[p][i]+h[i];
- interval[i].second=n;
- r+=interval[i].second-interval[i].first+;
- }
- LL mid,tmp;
- pair<int,int>now;
- while(l<=r)
- {
- mid=l+r>>;
- now=select(mid);
- if(check(now)) tmp=mid,r=mid-;
- else l=mid+;
- }
- now=select(tmp);
- l=now.first; r=now.second;
- for(int i=l;i<=r;++i) putchar(s[i]);
- }
- int main()
- {
- freopen("string.in","r",stdin);
- freopen("string.out","w",stdout);
- scanf("%d",&m);
- scanf("%s",s+);
- n=strlen(s+);
- for(int i=;i<=n;++i) a[i]=s[i]-'a'+;
- presa();
- get_height();
- prehash();
- solve();
- }
2016vijos 1-1 兔子的字符串(后缀数组 + 二分 + 哈希)的更多相关文章
- 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 657 Solved: 274[Su ...
- 【BZOJ4556】[Tjoi2016&Heoi2016]字符串 后缀数组+二分+主席树+RMQ
[BZOJ4556][Tjoi2016&Heoi2016]字符串 Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一 ...
- 【BZOJ3277/3473】串/字符串 后缀数组+二分+RMQ+双指针
[BZOJ3277]串 Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). Inpu ...
- POJ 2774 后缀数组 || 二分+哈希
Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 35607 Accepted: 14 ...
- BZOJ 4556 [Tjoi2016&Heoi2016]字符串 ——后缀数组 ST表 主席树 二分答案
Solution 1: 后缀数组暴力大法好 #include <map> #include <cmath> #include <queue> #include &l ...
- BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...
- 【bzoj4310】跳蚤 后缀数组+二分
题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...
- POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)
洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...
- BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ...
随机推荐
- nginx+php使用open_basedir限制站点目录防止跨站
以下三种设置方法均需要PHP版本为5.3或者以上.方法1)在Nginx配置文件中加入 fastcgi_param PHP_VALUE "open_basedir=$document_root ...
- hiho1258 Osu! Master
题目链接:http://hihocoder.com/problemset/problem/1258 题目大意:看能连击的次数 思路:水 看有多少个1和s就好了 #include <stdio.h ...
- 从App业务逻辑中提炼API接口
2.1 从App业务逻辑中提炼API接口 业务逻辑思维导图 功能-业务逻辑思维导图 基本功能模块关系 功能模块接口UML(设计出API) 在设计稿标注API 编写API文档 2.2 设计API的要点 ...
- 「SPOJ6340」「BZOJ1939」ZUMA - ZUMA【记忆化搜索】
题目链接 [洛谷传送门] 题解 \(f[i][j][k]\)表示在消除了\((i,j)\),在后面加上了\(k\)个珠子的总的珠子数. 考虑三种决策:(题目给出的\(k\)在下文表示成\(K\)) 决 ...
- 「洛谷1903」「BZOJ2120」「国家集训队」数颜色【带修莫队,树套树】
题目链接 [BZOJ传送门] [洛谷传送门] 题目大意 单点修改,区间查询有多少种数字. 解法1--树套树 可以直接暴力树套树,我比较懒,不想写. 稍微口胡一下,可以直接来一个树状数组套主席树,也就是 ...
- [HNOI2010]物品调度
题目描述 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置,从0到n-1依次编号,一开始0号位置空,其它的位置i上有编号为i的盒子.Lostm ...
- 在linux环境下搭建JDK+JAVA+Mysql,并完成jforum的安装
参考链接: YUM安装MySQL和JDK和Tomcat:http://cmdschool.blog.51cto.com/2420395/1696206/ http://www.cnblogs.com/ ...
- 阻止 form 回车 自动提交
问题:当form表单中只有一个input时,在input中按回车键会自动提交. 解决方案: 1.form元素上加onsubmit="return false"(推荐) 2.多个in ...
- 每天一个Linux命令 (转)
一. 文件目录操作命令: 1.每天一个linux命令(1):ls命令 2.每天一个linux命令(2):cd命令 3.每天一个linux命令(3):pwd命令 4.每天一个linux命令(4):mk ...
- 团体程序设计天梯赛(CCCC) L3014 周游世界 BFS证明
团体程序设计天梯赛代码.体现代码技巧,比赛技巧. https://github.com/congmingyige/cccc_code