Rabbit's String

Problem Description
Long long ago, there lived a lot of rabbits in the forest. One day, the king of the rabbit kingdom got a mysterious string and he wanted to study this string.

At first, he would divide this string into no more than k substrings. Then for each substring S, he looked at all substrings of S, and selected the one which has the largest dictionary order. Among those substrings selected in the second round, the king then choose one which has the largest dictionary order, and name it as a "magic string".

Now he wanted to figure out how to divide the string so that the dictionary order of that "magic string" is as small as possible.

Input
There are at most 36 test cases.

For each test case, the first line contains a integer k indicating the maximum number of substrings the king could divide, and the second line is the original mysterious string which consisted of only lower letters.

The length of the mysterious string is between 1 and 105 and k is between 1 and the length of the mysterious string, inclusive.

The input ends by k = 0.

Output
For each test case, output the magic string.
Sample Input
3
bbaa
2
ababa
0
 
Sample Output
b
ba
 
Hint

For the first test case, the king may divide the string into "b", "b" and "aa".
For the second test case, the king may divide the string into "aba" and "ba".

 
 
【题意】
  给出一个字符串,你最多将他分成K个子串,在每个子串中挑出字典序最大的子串,在从挑出的所有字符串中挑出字典序最大的字符串。现在希望,最后挑出的字符串足够小。
 
【分析】
 
  首先,这题具有单调性,而且是求最大串最小,所以我们可以二分答案串。
  怎么二分答案串呢,我们不是已经用后缀数组求出了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<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 100010
#define INF 0xfffffff char s[Maxn];
int l,c[Maxn],cl,k; void init()
{
scanf("%s",s);
l=strlen(s);cl=;
for(int i=;i<l;i++) c[++cl]=s[i]-'a'+;
} int mymin(int x,int y) {return x<y?x:y;} int rk[Maxn],sa[Maxn],Rs[Maxn],y[Maxn],wr[Maxn];
void get_sa(int m)
{
memcpy(rk,c,sizeof(rk));
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; int p=,ln=;
while(p<cl)
{
int kk=;
for(int i=cl-ln+;i<=cl;i++) y[++kk]=i;
for(int i=;i<=cl;i++) if(sa[i]>ln) y[++kk]=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]; for(int i=;i<=cl;i++) wr[i]=rk[i];
for(int i=cl+;i<=cl+ln;i++) wr[i]=;
p=,rk[sa[]]=;
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;
}
m=p,ln*=;
}
sa[]=rk[]=;
} int height[Maxn];
void get_he()
{
int kk=;
for(int i=;i<=cl;i++) if(rk[i]!=)
{
int j=sa[rk[i]-];
if(kk) kk--;
while(c[i+kk]==c[j+kk]&&i+kk<=cl&&j+kk<=cl) kk++;
height[rk[i]]=kk;
}
height[]=;
} struct hp
{
int x,y;
}a[Maxn];int al; bool cmp(hp x,hp y) {return (x.y==y.y)?(x.x>y.x):(x.y<y.y);} bool check(int x,int l)
{
al=;int minn=l;
if(l!=cl-sa[x]+) a[++al].x=sa[x],a[al].y=sa[x]+l-;
for(int i=x+;i<=cl;i++)
{
if(height[i]==) return ;
minn=mymin(minn,height[i]);
a[++al].x=sa[i],a[al].y=sa[i]+minn-;
}
sort(a+,a++al,cmp);
int p=;
if(al>) p=;
for(int i=;i<=al;i++)
{
if(a[i].x>a[p].x) a[++p]=a[i];
}
int mx=,cnt=;
for(int i=;i<=p;i++)
{
if(mx<a[i].x) mx=a[i].y,cnt++;
}
return cnt<k;
} int fffind(int x)
{
int l,r;bool ok=;
l=(x==)?:height[x]+;
r=cl-sa[x]+;
while(l<r)
{
int mid=(l+r)>>;
if(check(x,mid)) r=mid,ok=;
else l=mid+;
}
if(check(x,l)) ok=;
if(!ok) return -;
return l;
} void ffind()
{
int l=,r=cl;
while(l<r)
{
int mid=(l+r)>>;
if(fffind(mid)!=-) r=mid;
else l=mid+;
}
int x=fffind(l);
for(int i=sa[l];i<=sa[l]+x-;i++) printf("%c",c[i]-+'a');
printf("\n");
} int main()
{
while()
{
scanf("%d",&k);
if(k==) break;
init();
get_sa();
get_he();
ffind();
}
return ;
}

[HDU5030]

2016-07-20 15:17:13

 

【HDU 5030】Rabbit's String (二分+后缀数组)的更多相关文章

  1. HDU 5030 Rabbit's String

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5030 题意:给出一个长度为n的串S,将S分成最多K个子串S1,S2,……Sk(k<=K).选出每 ...

  2. hdu 6661 Acesrc and String Theory (后缀数组)

    大意: 求重复$k$次的子串个数 枚举重复长度$i$, 把整个串分为$n/i$块, 如果每块可以$O(1)$计算, 那么最终复杂度就为$O(nlogn)$ 有个结论是: 以$j$开头的子串重复次数最大 ...

  3. BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)

    求多串的最长公共字串. 法1: 二分长度+hash 传送门 法2: 二分+后缀数组 传送门 法3: 后缀自动机 拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再 ...

  4. hdu 5030 Rabbit&#39;s String(后缀数组&amp;二分法)

    Rabbit's String Time Limit: 40000/20000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  5. HDU5853 Jong Hyok and String(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5853 Description Jong Hyok loves strings. One da ...

  6. HDU 6194 string string string(后缀数组+RMQ)

    string string string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  7. HDU4080 Stammering Aliens(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...

  8. HDU 1403 Longest Common Substring(后缀数组,最长公共子串)

    hdu题目 poj题目 参考了 罗穗骞的论文<后缀数组——处理字符串的有力工具> 题意:求两个序列的最长公共子串 思路:后缀数组经典题目之一(模版题) //后缀数组sa:将s的n个后缀从小 ...

  9. 140. 后缀数组(hash + 二分 / 后缀数组)

    题目链接 : https://www.acwing.com/problem/content/description/142/ Hash + 二分 #include <bits/stdc++.h& ...

随机推荐

  1. Iframe跨域Session丢失的问题

    很久之前做的一个使用插件实现了图片批量上传,是通过IFrame加载上传面板的,使用google的chrome上传成功了就没怎么理了,最近同事测试时(使用的是360安全浏览器)老是出现上传不了图片的问题 ...

  2. ios各种手势,很有意思

    转自http://blog.csdn.net/likendsl/article/details/7554150 这哥们很厉害的 一.概述 iPhone中处理触摸屏的操作,在3.2之前是主要使用的是由U ...

  3. [转]rpcndr.h和wtypes.h冲突Bug的解决方案

    [转]rpcndr.h和wtypes.h冲突Bug的解决方案 http://blog.csdn.net/tzwh_86/article/details/9495133 rpcndr.h和wtypes. ...

  4. Entity Framework 学习第二天

    今天记录的内容不多,只是简单用一下Model first,新建项目,然后添加新建项,选择数据中的ado.net实体数据模型 这次我们选择空模型,然后右键,新增,实体 在这项demo中我打算建两个数据实 ...

  5. JSP基本知识

    JSP基本原理: JSP本质是Servlet(一个特殊的Java类),当用户向指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面.JSP通过在标准的HTML页面中嵌入Java代 ...

  6. 仿照CREATE_FUNC实现CCLayer中的返回CCScene* 的静态函数,宏包装成CREATE_SCENE(XXLayer)

    #define CREATE_SCENE(__TYPE__)\ CCScene *scene()\ { CCScene *scene=CCScene::create();\ __TYPE__ *lay ...

  7. PSPO表格

    一.项目计划总结: 周活动总结表 日期         任务 听课 编写程序 阅读课本 准备考试 日总计 周日 周一 周二 300 100 30 430 周三 100 50 30 180 周四 200 ...

  8. 用hoverclock插件实现HTML5时钟

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  9. HTML5表单学习笔记

    表单在网页设计中的作用非常重要,HTML5又增加了表单方面的诸多功能,包括增加input输入类型,input属性,form元素,form属性等,解决了我们以前比较头疼或者繁琐的功能. 新增的输入类型 ...

  10. 【CentOS】IBM X3650M4 IMM远程管理【转载】

    问题描述:          IBM X3650M4 IMM远程开机和关机   参考资料:             http://www.ibmsys.cn/blog/?p=201   问题解决: 一 ...