任意门:http://codeforces.com/gym/101954/problem/E

E. Locker Room

time limit per test

2.0 s

memory limit per test

256 MB

input

standard input

output

standard output

There are several strange rooms in Binary Casino and one of them is a locker room. You have to enter the locker room several times a day, two times being a minimum (before and after your shift). There is no key or access code needed to enter the locker room. There is a brand new security lock system instead.

The lock system presents you with a generated puzzle which you have to solve every time you want to enter the locker room. This system prevents possible intruders to enter the locker room, as the puzzle takes them a long time to solve. Only employees, after working in the casino for some time, manage to master the puzzle.

It is your second week in the casino and you have already been late three times because you didn't manage to solve the puzzle quickly enough. You therefore decided to write a program which solves the puzzle. The puzzle is as follows:

You are given a cyclic string of NN lowercase English letters. You have to choose and mark substrings (continuous segments of characters) of a given length KK until each character in the string is marked. Marking a substring does not change the original string and each character can be marked multiple times. The task is to print the lexicographically maximal substring among chosen substrings. In addition, the printed substring has to be lexicographically minimal possible.

For example, let "acdb" be the given string of length N=4N=4 and let K=3K=3. Then you can choose substrings "acd" and "bac" to mark the whole string. The puzzle solution is "bac".

Input

The first line of input contains two integers NN and KK (1≤N≤5⋅1051≤N≤5⋅105, 1≤K≤N1≤K≤N), describing the length of the given string and the length of marked substrings. The second line contains NN lowercase English letters – the given cyclic string.

Output

Output the lexicographically maximal substring among chosen substrings under the condition the result is lexicographically minimal possible.

Examples
input

Copy
4 3
acdb
output

Copy
bac
input

Copy
6 2
aababa
output

Copy
ab
input

Copy
10 4
abaaabaaba
output

Copy
aaba
input

Copy
1 1
v
output

Copy
v

题意概括:

在长度为 N 的主串中选取一个长度为 K 的子串可以把原主串全覆盖。

覆盖的条件是 选取的子串 s 把原串中所有长度为 K 并且字典序小于 s 的子串的字符标记之后(每个字符可被标记多次),

如果原串的全部字符都被标记,则当前选取的子串 s 可以覆盖这个主串。

求字典序最小的 s 。

原主串是一个环!!!

即最小化最大值。

解题思路:

模拟赛时想到的做法是 把所有长度为 K 的子串存进 set 然后枚举是否为这个答案,因为也是排好序的所以可以二分搜索,但判断条件依然是 O(N).结果在OJ上ML了

正解是后缀数组:

复制一遍原主串,因为是个环。

处理出后缀数组,然后二分后缀排名 t。

倍增版本 O(2*nlongn)

DC3版本  O(n+nlongn)

如何判断当前排名为 t 的后缀是可以的呢?

扫一遍原数组,遇到字典序排名大于 t 的后缀更新区间,

暴力是否有一段连续的区间长度大于等于 N,有则说明可以全覆盖。

如何统计这个区间呢?

定义一个起点 和 一个终点,如果遇到字典序比 s 大的后缀则跳过,否则更新终点指针。

如果当前枚举 的 i 已经大于 之前所覆盖的连续区间的终点 则更新 起点(即前面的连续区间已被打断)。

因为原主串是一个环,所以每次两点作差判断覆盖区间长度是否大于等于N。

如果当前排名 t 的后缀长度 小于 K,则它肯定无法覆盖原主串,因为相同字典序,长度长的字典序更大,暴力判断时,其所形成的连续区间必定小于 N;

如果当前排名 t 的后缀长度 大于等于 K,如何保证只取其长度为 K 的前缀作为答案呢?

这里很巧妙,统计区间时处理区间,总是 把终点更新为 当前小于 s (我们选取的后缀)的后缀起点 + K,也就是说只取前 K 个。

AC code:

 #include <bits/stdc++.h>
#define inc(i, j, k) for(int i = j; i <= k; i++)
#define rep(i, j, k) for(int i = j; i < k; i++)
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int maxn = int(3e6)+;///注意空间是要开到 3N 的
//const int N = maxn; #define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[maxn],wb[maxn],wv[maxn],Ws[maxn];
int r[maxn], sa[maxn], Rank[maxn], height[maxn]; int c0(int *r,int a,int b)
{return r[a]==r[b]&&r[a+]==r[b+]&&r[a+]==r[b+];} int c12(int k,int *r,int a,int b)
{if(k==) return r[a]<r[b]||r[a]==r[b]&&c12(,r,a+,b+);
else return r[a]<r[b]||r[a]==r[b]&&wv[a+]<wv[b+];} void Sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i=;i<n;i++) wv[i]=r[a[i]];
for(i=;i<m;i++) Ws[i]=;
for(i=;i<n;i++) Ws[wv[i]]++;
for(i=;i<m;i++) Ws[i]+=Ws[i-];
for(i=n-;i>=;i--) b[--Ws[wv[i]]]=a[i];
return;
}
void dc3(int *r,int *sa,int n,int m) //涵义与DA 相同
{
int i,j,*rn=r+n,*san=sa+n,ta=,tb=(n+)/,tbc=,p;
r[n]=r[n+]=;
for(i=;i<n;i++) if(i%!=) wa[tbc++]=i;
Sort(r+,wa,wb,tbc,m);
Sort(r+,wb,wa,tbc,m);
Sort(r,wa,wb,tbc,m);
for(p=,rn[F(wb[])]=,i=;i<tbc;i++)
rn[F(wb[i])]=c0(r,wb[i-],wb[i])?p-:p++;
if(p<tbc) dc3(rn,san,tbc,p);
else for(i=;i<tbc;i++) san[rn[i]]=i;
for(i=;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*;
if(n%==) wb[ta++]=n-;
Sort(r,wb,wa,ta,m);
for(i=;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
for(i=,j=,p=;i<ta && j<tbc;p++)
sa[p]=c12(wb[j]%,r,wa[i],wb[j])?wa[i++]:wb[j++];
for(;i<ta;p++) sa[p]=wa[i++];
for(;j<tbc;p++) sa[p]=wb[j++];
return;
} void calheight(int *r, int *sa, int n)
{
int i, j, k = ;
for(i = ; i <= n; i++) Rank[sa[i]] = i;
for(i = ; i < n; height[Rank[i++]] = k)
for(k?k--:,j=sa[Rank[i]-]; r[i+k]==r[j+k]; k++)
return;
} int N, K;
string str; bool check(int t)
{
int b = , e = -;
for(int i = ; i < N; i++){
if(Rank[i] > t) continue;
if(e < i) b = i;
e = i+K;
if(e-b >= N) return true;
}
return false;
} int main()
{
scanf("%d %d", &N, &K);
cin >> str;
str+=str;
// cout << str << endl;
int n_len = str.size();
for(int i = ; i < n_len; i++){
r[i] = str[i]-'a'+;
}
// n_len--;
r[n_len] = ;
dc3(r, sa, n_len+, );
calheight(r, sa, n_len);
// for(int i = 0; i < n_len; i++) cout << Rank[i] << endl; int L = , R = n_len, mid, ans;
while(L <= R){
mid = (L+R)>>;
if(check(mid)){
R = mid-;
ans = mid;
}
else L = mid+;
}
// cout << ans << endl;
string res;
for(int i = ; i < N; i++){
if(Rank[i] == ans){
res = str.substr(i, K);
cout << res << endl;
return ;
}
}
return ;
}

2018 - 2019 CTU Open Contest E. Locker Room 【后缀数组】的更多相关文章

  1. 2018 - 2019 CTU Open Contest H. Split Game 【SG函数】

    H. Split Game time limit per test 1.0 s memory limit per test 256 MB input standard input output sta ...

  2. 2018.11.24 spoj New Distinct Substrings(后缀数组)

    传送门 双倍经验(弱化版本) 考虑求出来heightheightheight数组之后用增量法. 也就是考虑每增加一个heightheightheight对答案产生的贡献. 算出来是∑∣S∣−heigh ...

  3. 2018.11.24 poj1743Musical Theme(二分答案+后缀数组)

    传送门 代码: 二分答案. 然后对于预处理的heightheightheight数组分成几段. 保证每一段中都是连续的几个heightheightheight并且这些heightheightheigh ...

  4. COCI 2018/2019 CONTEST #2 T4 Maja T5Sunčanje Solution

    COCI 2018/2019 CONTEST #2 T4 T5 Solution abstract 花式暴力 #2 T5 Sunčanje 题意 按顺序给你1e5个长方形(左下角坐标&& ...

  5. 20172328 2018—2019《Java软件结构与数据结构》第二周学习总结

    20172328 2018-2019<Java软件结构与数据结构>第二周学习总结 概述 Generalization 本周学习了第三章集合概述--栈和第四章链式结构--栈.主要讨论了集合以 ...

  6. 2018 German Collegiate Programming Contest (GCPC 18)

    2018 German Collegiate Programming Contest (GCPC 18) Attack on Alpha-Zet 建树,求lca 代码: #include <al ...

  7. (寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)

    layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa&q ...

  8. 2019 Multi-University Training Contest 8

    2019 Multi-University Training Contest 8 C. Acesrc and Good Numbers 题意 \(f(d,n)\) 表示 1 到 n 中,d 出现的次数 ...

  9. 2019 Multi-University Training Contest 7

    2019 Multi-University Training Contest 7 A. A + B = C 题意 给出 \(a,b,c\) 解方程 \(a10^x+b10^y=c10^z\). tri ...

随机推荐

  1. 撩课-Web大前端每天5道面试题-Day23

    1.为什么用Nodejs,它有哪些优缺点? 优点: 事件驱动,通过闭包很容易实现客户端的生命活期. 不用担心多线程,锁,并行计算的问题 V8引擎速度非常快 对于游戏来说,写一遍游戏逻辑代码,前端后端通 ...

  2. Linux的虚拟内存管理-如何分配和释放内存,以提高服务器在高并发情况下的性能,从而降低了系统的负载

    Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...

  3. Maven 项目管理从未如此通畅

    一,写在前面 Maven到底是什么?它能做些什么?能为我们的开发工作提供什么样的帮助?为什么会有如此大的知名度?另外,常听大厂的人说“私服”,工具管理吧啦吧啦的一堆也是不明觉厉.相信仁者见仁,着智者见 ...

  4. python学习之老男孩python全栈第九期_数据库day002知识点总结 —— MySQL数据库day2(全部)

    一. 复习1. MySQL: - 服务端 - 客户端2. 通信交流 - 授权 - SQL语句 - 数据库 创建数据库: create database db1 default charset utf8 ...

  5. 2017年5月22日 HTML基础知识(一)

    一.Html 结构 1.1.HTML基本文档格式—<html> 标记 —<html>文档的头部好和主体内容 </html>  根标记 —<head> 文 ...

  6. 【canvas系列】用canvas实现一个colorpicker(类似PS的颜色选择器)

    每个浏览器都有自己的特点,比如今天要做的colorpicker就是,一千个浏览器,一千个哈姆雷特,一千个colorpicker.今天canvas系列就用canvas做一个colorpicker. ** ...

  7. Difference between ReLU、LReLU、PReLU、CReLU、ELU、SELU

    激活函数 ReLU.LReLU.PReLU.CReLU.ELU.SELU  的定义和区别 ReLU tensorflow中:tf.nn.relu(features, name=None) LReLU ...

  8. 签署您的应用--手动签署 APK

    签署您的应用 本文内容 证书和密钥库 签署您的调试构建 调试证书的有效期 管理您的密钥 使用 Google Play 应用签名 自行管理您的密钥和密钥库 签署 APK 生成密钥和密钥库 手动签署 AP ...

  9. 一种特殊场景下的HASH JOIN的优化为NEST LOOP.

    应用场景: 有如下的SQL: select t.*, t1.ownerfrom t, t1where t.id=t1.id; 表t ,t1的数据量比较大,比如200W行.但是两张表能关联的行数却很少, ...

  10. @autowired 和@resource的区别

    1. @Autowired与@Resource都可以用来装配bean.  都可以写在字段上,或写在setter方法上. 2. @Autowired默认按类型装配(这个注解是属业spring的),默认情 ...