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. iPhone的震动 基于SDK8.0 Swift实现

    导入AudioToolbox.framework包 在swift文件中  import AudioToolbox AudioServicesPlaySystemSound(SystemSoundID. ...

  2. (转)android Fragments详解一:概述

    Fragment是activity的界面中的一部分或一种行为.你可以把多个Fragment们组合到一个activity中来创建一个多面界面并且你可以在多个activity中重用一个Fragment.你 ...

  3. Machine Learning 学习笔记 (4) —— 广义线性模型

    本系列文章允许转载,转载请保留全文! [请先阅读][说明&总目录]http://www.cnblogs.com/tbcaaa8/p/4415055.html 1. 指数分布族简介 之前的文章分 ...

  4. Z_blog博客尝试 http://www.uuxin.com/

    原来的博客由于没有备份所有数据全部丢失,很是郁闷. 又用Z-BLOG新建了一个博客.http://www.uuxin.com

  5. Notes of the scrum meeting(12.8)

    meeting time:18:00~18:30p.m.,December 8th,2013 meeting place:20号公寓前 attendees: 顾育豪                   ...

  6. vs2012 condition_variable notify_one 崩溃

    vs2012项目中用到 condition_variable系统方法,程序运行过程过程中偶尔出现notify_one崩溃, 程序运行的服务器系统版本是windows server 2008 R2 SP ...

  7. [转]Similarities between Hibernate and JDBC objects

  8. Codeforces Round #353 (Div. 2) E. Trains and Statistic 线段树+dp

    题目链接: http://www.codeforces.com/contest/675/problem/E 题意: 对于第i个站,它与i+1到a[i]的站有路相连,先在求所有站点i到站点j的最短距离之 ...

  9. 802.11 wireless 四

    802.11 wireless 4spread spectrum(扩频 - 基于香农定理的算法)1.窄带和扩频是发送信号的两种不同方式2.扩频技术使用更小的能量在波峰3.带宽的需要,基于发送数据的量频 ...

  10. JRebel: ERROR Could not define reloadable class 'com.sun.proxy.$Proxy118': java.lang.OutOfMemoryError: PermGen space

    MyEclipse由于配置了JRebel,所以是它报错,不过根本问题还是:java.lang.OutOfMemoryError: PermGen space 现在按照经验调整内存大小. 在MyEcli ...