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. Sharepoint 2010 RBS 的安装和配置

    基本上按照微软官方的配置方法配置就行了. 给下地址:微软官方     涂大神 找RBS的安装文件也是个问题,微软的链接好像失效了.我使用的是RBS下载.这里也有. 我的环境是数据库两台故障群集转移,微 ...

  2. 解决ubuntu字体发虚,网页字体发虚

    好吧,哥也不知所以然,只是突然间所有东西的字体都发虚了~~后来发现是应该是语言支持搞的鬼,卸载掉下面的东东就没事了 sudo apt-get remove fonts-arphic-ukai ttf- ...

  3. 使用itunes同步ios时丢失照片恢复

    因没有备份,在使用同步功能后,发现照片被清空了,找到恢复方法,分享之! from:http://modmyi.com/forums/native-iphone-ipod-touch-app-discu ...

  4. Sprint计划会议1

    会议时间:4.15.晚9点 会议地点:学一食堂2楼 会议进程 • 首先我们讨论了实验第一个Sprint1要实现的功能(用户登录及信息录入).•  之后对任务进行了认领.•  最后每个人对自己的任务进行 ...

  5. xml基础学习笔记05

    Xpath快速解析 如题一样,本篇主要说说Xpath快速查找XML文档   * Xpatn.Xquery,是专门用来查询xml的语言   * 查询xml非常快   Xpatn.Xquery,是专门用来 ...

  6. Careercup - Google面试题 - 6332750214725632

    2014-05-06 10:18 题目链接 原题: Given a ,) (,) (,), (,) should be returned. Some suggest to use Interval T ...

  7. 22、DDMS(转载)

    本文是转载,出处为http://www.xuebuyuan.com/1291595.html 如需删除本文,请私信我,谢谢 DDMS DDMS是一款Google* 提供的应用,可作为独立的工具运行,也 ...

  8. ZBar之自定义二维码扫描

    // // YvanQRCodeViewController.m // zBar // // Created by City--Online on 15/6/8. // Copyright (c) 2 ...

  9. 你所必须掌握的三种异步编程方法callbacks,listeners,promise

    目录: 前言 Callbacks Listeners Promise 前言 coder都知道,javascript语言运行环境是单线程的,这意味着任何两行代码都不能同时运行.多任务同时进行时,实质上形 ...

  10. X86架构CPU的逻辑原理

    本篇只是初略介绍X86的逻辑运行原理,并不涉及物理层面和汇编层面的知识. 一.冯洛伊曼体系的运作过程: 1.CPU的历史就不扯了,有兴趣的朋友可以网上搜一下. 2.X86CPU是基于冯洛伊曼架构体系, ...