HDU 4898 The Revenge of the Princess’ Knight(后缀数组+二分+暴力)(2014 Multi-University Training Contest 4)
The devil’s birthday is approaching, of course, she wants some beautiful gift from the king. The king search everywhere in this kingdom, and finds a beautiful ring for her.
For simplicity, we can see this ring as a ring(so it is a cycle!) of lowercase characters with length n.
The king’s cute daughter, WJMZBMR, gets nothing from her father in her birthday. She feels very sad. By the influence of the king and the devil, this kingdom is full of lolicon, some people think the king is unfair to his kawayi daughter, so they form a party called princess’s knight and plan to destroy king’s gift for the devil to make things fair.
The knight of the knight (or the lolicon of the lolicon), a man called z*p, has the chance to destroy the ring now. But due to his limitless of strength, he can only cut this ring into exactly k continuous parts. To please the princess, he want among those part, the maximum one respect to the lexicographical order is minimized. How can he do it?
For each test case, the first line contains two integers n and k, which are the length of the ring and the parts z*p can cut.
The next line is a string represent the ring.
n <= 1000,1<=k<=n.
T <= 5.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL; const int MAXN = ; char s[MAXN];
int sa[MAXN], rank[MAXN], c[MAXN], tmp[MAXN], height[MAXN];
int n, k, T; void makesa(int n, int m) {
memset(c, , m * sizeof(int));
for(int i = ; i < n; ++i) ++c[rank[i] = s[i]];
for(int i = ; i < m; ++i) c[i] += c[i - ];
for(int i = ; i < n; ++i) sa[--c[rank[i]]] = i;
for(int k = ; k < n; k <<= ) {
for(int i = ; i < n; ++i) {
int j = sa[i] - k;
if(j < ) j += n;
tmp[c[rank[j]]++] = j;
}
int j = c[] = sa[tmp[]] = ;
for(int i = ; i < n; ++i) {
if(rank[tmp[i]] != rank[tmp[i - ]] || rank[tmp[i] + k] != rank[tmp[i - ] + k])
c[++j] = i;
sa[tmp[i]] = j;
}
memcpy(rank, sa, n * sizeof(int));
memcpy(sa, tmp, n * sizeof(int));
}
} void calheight(int n) {
for(int i = , k = ; i < n; height[rank[i++]] = k) {
k -= (k > );
int j = sa[rank[i] - ];
while(s[i + k] == s[j + k]) ++k;
}
} int logn[MAXN];
int best[][MAXN]; void init(int n = ) {
static bool done = false;
if(done) return ;
logn[] = -;
for(int i = ; i <= n; ++i)
logn[i] = logn[i - ] + ((i & (i - )) == );
done = true;
} void initRMQ(int n) {
init();
for(int i = ; i <= n; ++i) best[][i] = height[i];
for(int i = ; i <= logn[n]; ++i) {
int ed = n - ( << i) + ;
for(int j = ; j <= ed; ++j)
best[i][j] = min(best[i - ][j], best[i - ][j + ( << (i - ))]);
}
} int lcp(int a, int b) {
if(a == b) return n;
a = rank[a], b = rank[b];
if(a > b) swap(a, b);
++a;
int t = logn[b - a + ];
return min(best[t][a], best[t][b - ( << t) + ]);
} int cmp(int x, int n, int y, int m) {
int t = lcp(x, y);
if(n > t && m > t) return s[x + t] - s[y + t];
return n - m;
} struct Node {
int pos, len;
Node() {}
Node(int pos, int len): pos(pos), len(len) {}
bool operator < (const Node &rhs) const {
return cmp(pos, len, rhs.pos, rhs.len) < ;
}
void print() {
for(int i = pos; i < pos + len; ++i)
putchar(s[i]);
puts("");
}
}; const int MAXV = MAXN >> ;
Node src[MAXV * MAXV];
bool mat[MAXV][MAXV], ban[MAXV];
int go[MAXV], cnt[MAXV]; bool check(Node p) {
memset(mat, , sizeof(mat));
memset(ban, , sizeof(ban));
for(int i = ; i < n; ++i) {
go[i] = n;
if(cmp(i, n, p.pos, p.len) >= ) go[i] = min(go[i], min(p.len, lcp(p.pos % n, i)));
cnt[i] = go[i];
for(int j = i + ; j <= i + go[i]; ++j)
mat[j % n][i] = true;
}
for(int _ = ; _ < n; ++_) {
bool flag = false;
for(int i = ; i < n; ++i) if(!ban[i] && !cnt[i]) {
ban[i] = flag = true;
for(int j = ; j < n; ++j) cnt[j] -= mat[i][j];
}
if(!flag) break;
}
int c = ;
for(int i = ; i < n; ++i) if(cnt[i]) cnt[c++] = cnt[i];
for(int st = ; st < c; ++st) {
int x = st, y = ;
while(x < st + c) x += cnt[x % c], ++y;
if(c >= k && y <= k) return true;
}
return false;
} void solve() {
int c = ;
for(int i = ; i < n; ++i)
for(int j = ; j <= n; ++j) src[c++] = Node(i, j);
sort(src, src + c);
//c = unique(src, src + c) - src;
int l = , r = c;
while(l < r) {
int mid = (l + r) >> ;
//src[mid].print();
if(!check(src[mid])) l = mid + ;
else r = mid;
}
src[l].print();
} int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &k);
scanf("%s", s);
memcpy(s + n, s, n * sizeof(char));
s[n << ] = ;
makesa( * n + , );
calheight( * n);
initRMQ( * n);
solve();
}
}
HDU 4898 The Revenge of the Princess’ Knight(后缀数组+二分+暴力)(2014 Multi-University Training Contest 4)的更多相关文章
- hdu 4898 The Revenge of the Princess’ Knight
传送阵:http://acm.hdu.edu.cn/showproblem.php?pid=4898 题目大意:一个首尾相连的字符串,将其分为k个子串,使得最大的字串最小 将所有子串排序,输出第k小即 ...
- HDU 4898 The Revenge of the Princess’ Knight ( 2014 Multi-University Training Contest 4 )
题意:给定一个环形字符串,让他把它分成k份,使得最大的字典序 最小. 思路:二分答案,首先很明显答案所有可能是 n*n种 排序可以先求出最长公共前缀,这样比较就只需要比较公共前缀的下一位就能比较出两 ...
- 【HDU 4898】 The Revenge of the Princess’ Knight (后缀数组+二分+贪心+...)
The Revenge of the Princess’ Knight Problem Description There is an old country and the king fell in ...
- HDU 6278 - Just h-index - [莫队算法+树状数组+二分][2018JSCPC江苏省赛C题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6278 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
- HDU 5008 Boring String Problem(后缀数组+二分)
题目链接 思路 想到了,但是木写对啊....代码 各种bug,写的乱死了.... 输出最靠前的,比较折腾... #include <cstdio> #include <cstring ...
- HDU 4691 正解后缀数组(暴力也能过)
本来是个后缀数组,考察算法的中级题目,暴力居然也可以水过,就看你跳不跳坑了(c++和G++返回结果就很不一样,关键看编译器) 丝毫不差的代码,就看运气如何了.唯一差别c++还是G++,但正解是后缀数组 ...
- hdu 3038 How Many Answers Are Wrong(种类并查集)2009 Multi-University Training Contest 13
了解了种类并查集,同时还知道了一个小技巧,这道题就比较容易了. 其实这是我碰到的第一道种类并查集,实在不会,只好看着别人的代码写.最后半懂不懂的写完了.然后又和别人的代码进行比较,还是不懂,但还是交了 ...
- HDU 5558 后缀数组+二分
题意有一些绕,但其实就是对于不断变化的i,求以j(0=j<i)使得suffix[j]与suffix[i]的最长公共前缀最长,如果有多个j,则取最小的j. 可以在rank数组中二分,在1-rank ...
- hdu 6194 沈阳网络赛--string string string(后缀数组)
题目链接 Problem Description Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle M ...
随机推荐
- 冒泡排序与插入排序(C#实现)
本人应届生面试,发现被问了2次关于排序的算法.当时竟然没写出来!!!好吧,可能是用库函数多了,很久没搞算法了,在纸上写没感觉吧. 今天花了1个多小时写了下冒泡排序与插入排序(C#实现),并写了注释和小 ...
- nrf51822裸机教程-SPI(主)
关于SPI总线的介绍这里就不细说了,网上有很多介绍SPI总线时序的. SPI总线的本质就是一个环形总线结构,在时钟驱动下两个双向移位寄存器进行数据交换. 所以SPI总线的特色就是:传输一字节数据的同时 ...
- SHELL 八大扩展
最近在梳理bash知识的的过程中,有幸阅读了man bash文档,一时间犹如醍醐灌顶一般,很多当初不明白的地方都豁然开朗,现在就其中的一点做一分享,同时也为man bash做一下广告,当你面对bash ...
- Delphi调用约定
Register Calling Convention Ojbect Pascal的默认调用约定为register,寄存器调用约定会将前三个参数依次放入eax,edx,ecx,返回值是eax(根据类型 ...
- 从while(cin>>a)开始探讨cin
1. 首先cin>>a返回的是左操作数,也就是返回cin. cin的条件状态中: cin.eof() 判断流是否到达文件的结束符 cin.fail() 判断IO操作是否失败 在 ...
- Arcgis for JS之Cluster聚类分析的实现(基于区域范围的)
原文:Arcgis for JS之Cluster聚类分析的实现(基于区域范围的) 咱们书接上文,在上文,实现了基于距离的空间聚类的算法实现,在本文,将继续介绍空间聚类之基于区域范围的实现方式,好了,闲 ...
- proxy解析
知其所以然 本文不是教程向,倾向于分析科学上网的一些原理.知其所以然,才能更好地使用工具,也可以创作出自己的工具. 科学上网的工具很多,八仙过海,各显神通,而且综合了各种技术.尝试从以下四个方面来解析 ...
- imx6 关闭 otg host
参考文档: http://www.cnblogs.com/zengjfgit/p/4711336.html make menuconfig 去掉Support for DR host port on ...
- LeetCode Majority Element I && II
原题链接在这里:Majority Element I,Majority Element II 对于Majority Element I 来说,有多重解法. Method 1:最容易想到的就是用Hash ...
- jquery 日历插件datepicker格式调整
<script> $(function() { $("#datepicker").datepicker({ dateFormat: "yy/mm/dd&quo ...