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. Jni中C++和Java的参数传递

    Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...

  2. yum代理设置

    vi /etc/yum.conf 加入以下:proxy=http://代理服务器ip:port 如果代理需要账号密码:proxy_username=userproxy_password=密码

  3. Python实现ID3(信息增益)

    Python实现ID3(信息增益) 运行环境 Pyhton3 treePlotter模块(画图所需,不画图可不必) matplotlib(如果使用上面的模块必须) 计算过程 st=>start: ...

  4. h264码流分析

    ---------------------------------------------------------------------------------------------------- ...

  5. 文档对象模型(DOM)

    文档对象模型(DOM)    DOM可以将任何HTML或XML文档描绘成一个由多层节点构成的结构.节点分为几种不同的类型:文档型节点.元素节点.特性节点.注释节点等共有12种节点类型.DOM1级定义了 ...

  6. 微软Hololens学院教程-Hologram 220-空间声音(Spatial sound )【本文是老版本,与最新的微软教程有出入】

    这是老版本的教程,为了不耽误大家的时间,请直接看原文,本文仅供参考哦! 原文链接https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/ho ...

  7. POJ 2960 博弈论

    题目链接: http://poj.org/problem?id=2960 S-Nim Time Limit: 2000MS Memory Limit: 65536K 问题描述 Arthur and h ...

  8. 编译器手工开栈(hdu可以其他可以尝试)

    做题的时候经常遇到深度递归的,当然也可以改成非递归形式.如果写成递归形式会爆栈,所以可以用手工扩展栈. C++ (一般用C++提交,所以就推荐这种了) #pragma comment(linker, ...

  9. LightOJ 1140 How Many Zeroes

    题意:写出一个给定区间的每个数,求出一共写了多少个零. 解法:数位DP,定义dp[len][flag][num]:len的定义为数位的长度,flag定义为前导0和没有前导0的两种状态,num定义为写的 ...

  10. 2010 Asia Fuzhou Regional Contest

    A hard Aoshu Problem http://acm.hdu.edu.cn/showproblem.php?pid=3699 用深搜写排列,除法要注意,还有不能有前导零.当然可以5个for, ...