2018 - 2019 CTU Open Contest E. Locker Room 【后缀数组】
任意门:http://codeforces.com/gym/101954/problem/E
E. Locker Room
2.0 s
256 MB
standard input
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".
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 the lexicographically maximal substring among chosen substrings under the condition the result is lexicographically minimal possible.
4 3
acdb
bac
6 2
aababa
ab
10 4
abaaabaaba
aaba
1 1
v
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 【后缀数组】的更多相关文章
- 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 ...
- 2018.11.24 spoj New Distinct Substrings(后缀数组)
传送门 双倍经验(弱化版本) 考虑求出来heightheightheight数组之后用增量法. 也就是考虑每增加一个heightheightheight对答案产生的贡献. 算出来是∑∣S∣−heigh ...
- 2018.11.24 poj1743Musical Theme(二分答案+后缀数组)
传送门 代码: 二分答案. 然后对于预处理的heightheightheight数组分成几段. 保证每一段中都是连续的几个heightheightheight并且这些heightheightheigh ...
- COCI 2018/2019 CONTEST #2 T4 Maja T5Sunčanje Solution
COCI 2018/2019 CONTEST #2 T4 T5 Solution abstract 花式暴力 #2 T5 Sunčanje 题意 按顺序给你1e5个长方形(左下角坐标&& ...
- 20172328 2018—2019《Java软件结构与数据结构》第二周学习总结
20172328 2018-2019<Java软件结构与数据结构>第二周学习总结 概述 Generalization 本周学习了第三章集合概述--栈和第四章链式结构--栈.主要讨论了集合以 ...
- 2018 German Collegiate Programming Contest (GCPC 18)
2018 German Collegiate Programming Contest (GCPC 18) Attack on Alpha-Zet 建树,求lca 代码: #include <al ...
- (寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)
layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa&q ...
- 2019 Multi-University Training Contest 8
2019 Multi-University Training Contest 8 C. Acesrc and Good Numbers 题意 \(f(d,n)\) 表示 1 到 n 中,d 出现的次数 ...
- 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 ...
随机推荐
- Java数据类型和不同数据类型在JVM内存分配
1.java数据类型分类 Java语言是强类型(Strongly typed)语言,强类型包含两方面的含义:①所有的变量必须先声明,后使用:②指定类型的变量只能接受类型与之匹配的值.这意味着每个变量和 ...
- Java中获取32位UUID
public class createUUID { public static void main(String[] args) { String uuid = UUID.randomUUID().t ...
- MPVUE - 使用vue.js开发微信小程序
MPVUE - 使用vue.js开发微信小程序 什么是mpvue? mpvue 是美团点评前端团队开源的一款使用 Vue.js 开发微信小程序的前端框架.框架提供了完整的 Vue.js 开发体验,开发 ...
- js-数组中查找特定元素并返回所有该元素的索引
//在数组中查找所有出现的x,并返回一个包含匹配索引的数组 function findall(a,x){ var results=[], len=a.length, pos=0; while(pos& ...
- 转:PHP导出excel文件的几种方式
PHP导出excel文件的几种方式 文章来源:http://www.cnblogs.com/fredshare/archive/2012/10/29/2744243.html 先说说动态生成的内容当作 ...
- MS SQL Server数据库查询优化技巧
[摘 要]本文主要是对MS SQL Server数据库查询优化技巧进行了说明和分析,对索引使用.查询条件以及数据表的设计等进行了阐述.中国论文网 http://www.xzbu.com/2/view- ...
- maven 编译插件指定jdk版本的两种方式
第一种方式: <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration&g ...
- windows 命令行报错:file(s) not in client view
今天在执行p4 sync命令时报错:File(s) not in client view,查找后发现其实是未连接上p4服务器.需要重新设置P4PORT=服务器地址 即可解决(参考链接:https:/ ...
- Ext根据条件显示隐藏列
Ext根据条件显示隐藏列 写在ExtonReady函数里面,并在表格成功渲染之后,可以添加判断是否隐藏或者显示某一列 /* 判断是否显示版本号一列 */ var showVersionFlag = ' ...
- tomcat idea optinos
-server -XX:PermSize=128M -XX:MaxPermSize=256m -Xms512m -Xmx1024m