Problem Description
There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse any request from the devil. Also, this devil is looking like a very cute Loli.

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?

 
Input
The first line contains an integer T, denoting the number of the test cases.
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.

 
Output
For each case, output the maximum part in one line.
 
题目大意:给一个环状字符串,要求分成k个连续子串,使得字典序最大的子串最小。求这个子串。
思路:http://www.cnblogs.com/L-Ecry/p/3888396.html
http://blog.csdn.net/t1019256391/article/details/38347293
PS:据说n≤10W还是能做?
 
代码(2531MS):
 #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)的更多相关文章

  1. hdu 4898 The Revenge of the Princess’ Knight

    传送阵:http://acm.hdu.edu.cn/showproblem.php?pid=4898 题目大意:一个首尾相连的字符串,将其分为k个子串,使得最大的字串最小 将所有子串排序,输出第k小即 ...

  2. HDU 4898 The Revenge of the Princess’ Knight ( 2014 Multi-University Training Contest 4 )

    题意:给定一个环形字符串,让他把它分成k份,使得最大的字典序 最小. 思路:二分答案,首先很明显答案所有可能是 n*n种  排序可以先求出最长公共前缀,这样比较就只需要比较公共前缀的下一位就能比较出两 ...

  3. 【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 ...

  4. 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 ...

  5. HDU 5008 Boring String Problem(后缀数组+二分)

    题目链接 思路 想到了,但是木写对啊....代码 各种bug,写的乱死了.... 输出最靠前的,比较折腾... #include <cstdio> #include <cstring ...

  6. HDU 4691 正解后缀数组(暴力也能过)

    本来是个后缀数组,考察算法的中级题目,暴力居然也可以水过,就看你跳不跳坑了(c++和G++返回结果就很不一样,关键看编译器) 丝毫不差的代码,就看运气如何了.唯一差别c++还是G++,但正解是后缀数组 ...

  7. hdu 3038 How Many Answers Are Wrong(种类并查集)2009 Multi-University Training Contest 13

    了解了种类并查集,同时还知道了一个小技巧,这道题就比较容易了. 其实这是我碰到的第一道种类并查集,实在不会,只好看着别人的代码写.最后半懂不懂的写完了.然后又和别人的代码进行比较,还是不懂,但还是交了 ...

  8. HDU 5558 后缀数组+二分

    题意有一些绕,但其实就是对于不断变化的i,求以j(0=j<i)使得suffix[j]与suffix[i]的最长公共前缀最长,如果有多个j,则取最小的j. 可以在rank数组中二分,在1-rank ...

  9. hdu 6194 沈阳网络赛--string string string(后缀数组)

    题目链接 Problem Description Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle M ...

随机推荐

  1. jquery的$.ajax async使用详解

      async在jquery ajax中是一个同步参数了,我们下面来给大家介绍在jquery ajax中使用async时碰到的一些问题与方法介绍,希望例子能给各位同学带来一些帮助哦.   async默 ...

  2. CDH(Cloudera)与hadoop(apache)对比

    本文出自:CDH(Cloudera)与hadoop(apache)对比http://www.aboutyun.com/thread-9225-1-1.html(出处: about云开发)   问题导读 ...

  3. 注册、启动、停止windows服务

    找到本机InstallUtil.exe命令 命令行下注册服务InstallUtil.exe D:\XXXXService.exe 启动服务 net start XXXXService 停止服务net ...

  4. TCP粘包

    一.通信协议TCP/UDP: TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务.客户端和服务器端都要有一一成对的socket, 因此 ...

  5. zero1--hibernate注解02

  6. Spring第十一篇——–Spring整合Hibernate之配置数据源

    DataSource(数据源)提供了一个标准化的取得数据库连接的方式,通过getConnection()方法即可取得数据库的连接,Spring也提供了数据库连接池(DataBase connectio ...

  7. Android各个版本 版本号对应关系表

    Platform Version API Level VERSION_CODE Notes Android 5.0 21 LOLLIPOP Platform Highlights Android 4. ...

  8. nginx的内存管理

    先来看内存池的实现,nginx的内存池实现的非常简单. 这里内存池的一些图表可以看老朱同学的slides : http://blog.zhuzhaoyuan.com/2009/09/nginx-int ...

  9. Linux权限值问题

    0660:从左向右:第一位:(我不清楚,也没有用过)第二位:当前用户的经权限:6=110(二进制),每一位分别对就 可读,可写,可执行,,6说明当前用户可读可写不可执行第三位:group组用户,6的意 ...

  10. android framework浅析_转

    Android系统从底向上一共分了4层,每一层都把底层实现封装,并暴露调用接口给上一层. 1. Linux内核(Linux Kernel) 1)Android运行在linux kernel 2.6之上 ...