BZOJ_1692_[Usaco2007 Dec]队列变换_后缀数组
BZOJ_1692_[Usaco2007 Dec]队列变换_后缀数组
Description
FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”。在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过。 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie、Sylvia、Dora,登记人员就把这支队伍登记为BSD)。登记结束后,组委会将所有队伍的登记名称按字典序升序排列,就得到了他们的出场顺序。 FJ最近有一大堆事情,因此他不打算在这个比赛上浪费过多的时间,也就是说,他想尽可能早地出场。于是,他打算把奶牛们预先设计好的队型重新调整一下。 FJ的调整方法是这样的:每次,他在原来队列的首端或是尾端牵出一头奶牛,把她安排到新队列的尾部,然后对剩余的奶牛队列重复以上的操作,直到所有奶牛都被插到了新的队列里。这样得到的队列,就是FJ拉去登记的最终的奶牛队列。 接下来的事情就交给你了:对于给定的奶牛们的初始位置,计算出按照FJ的调整规则所可能得到的字典序最小的队列。
Input
* 第1行: 一个整数:N
* 第2..N+1行: 第i+1行仅有1个'A'..'Z'中的字母,表示队列中从前往后数第i 头奶牛名字的首字母
Output
* 第1..??行: 输出FJ所能得到的字典序最小的队列。每行(除了最后一行)输 出恰好80个'A'..'Z'中的字母,表示新队列中每头奶牛姓名的首 字母
Sample Input
A
C
D
B
C
B
输入说明:
FJ有6头顺次排好队的奶牛:ACDBCB
Sample Output
ABCBCD
暴力。
考虑暴力怎么做,从两边找找到第一个不一样的,比较两边的字典序哪个小拿哪个。
但我们不能一次都拿走,比如AAABCAAA,拿AAAB显然不如拿AAAA,于是这个暴力决定了我们每次只能拿一个。
拿一次也可以,不妨降低比较字典序的时间,可以把原串的反串贴在后面,然后求后缀数组,比较两个串的rank即可。
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 600050
char s[N];
int r[N],sa[N],wa[N],wb[N],wv[N],rank[N],height[N],n,ws[N];
inline char nc() {static char buf[100000],*p1,*p2;return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
inline int rd() {int x=0; char c=nc(); while(c<'0'||c>'9') c=nc(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=nc(); return x;}
inline int rc() {char c=nc();while(c<'A'||c>'Z')c=nc(); return c-'A'+1;}
void build_suffix_array() {
int i,j,p,m=28,*x=wa,*y=wb,*t;
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[x[i]=r[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
for(j=p=1;p<n;j<<=1,m=p) {
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]-j>=0) y[p++]=sa[i]-j;
for(i=0;i<n;i++) wv[i]=x[y[i]];
for(i=0;i<m;i++) ws[i]=0;
for(i=0;i<n;i++) ws[wv[i]]++;
for(i=1;i<m;i++) ws[i]+=ws[i-1];
for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++) {
if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1;
else x[sa[i]]=p++;
}
}
for(i=1;i<n;i++) rank[sa[i]]=i;
for(i=p=0;i<n-1;height[rank[i++]]=p)
for(p?p++:0,j=sa[rank[i]-1];r[i+p]==r[j+p];p++);
}
int main() {
n=rd();
int i,ln=n,k;
for(i=0;i<n;i++) r[i]=rc();
r[n]=0;
for(i=n+1;i<=n+n;i++) r[i]=r[n+n-i];
n<<=1; r[n++]=0;
build_suffix_array();
int j=ln-1; i=0;
for(k=1;k<=ln;k++) {
if(rank[i]<rank[ln+ln-j]) printf("%c",r[i++]+'A'-1);
else printf("%c",r[j--]+'A'-1);
if(k%80==0) puts("");
}
return 0;
}
BZOJ_1692_[Usaco2007 Dec]队列变换_后缀数组的更多相关文章
- [bzoj1692][Usaco2007 Dec]队列变换_后缀数组_贪心
队列变换 bzoj-1692 Usaco-2007 Dec 题目大意:给定一个长度为$n$的字符串.每次从头或尾取出一个字符加到另一个字符串里.要求变换后生成的字符串字典序最小,求字典序最小的字符串. ...
- 【BZOJ】1692 & 1640: [Usaco2007 Dec]队列变换(后缀数组+贪心)
http://www.lydsy.com/JudgeOnline/problem.php?id=1692 http://www.lydsy.com/JudgeOnline/problem.php?id ...
- 【bzoj1692】[Usaco2007 Dec]队列变换 贪心+后缀数组
题目描述 FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. ...
- [BZOJ 1692] [Usaco2007 Dec] 队列变换 【后缀数组 + 贪心】
---恢复内容开始--- 题目链接:BZOJ - 1692 题目分析 首先,有个比较简单的贪心思路:如果当前剩余字符串的两端字母不同,就选取小的字母,这样显然是正确的. 然而若两端字母相同,我们怎么选 ...
- [bzoj1692][Usaco2007 Dec]队列变换——贪心+后缀数组
Brief Description 给定一个数列,您每次可以把数列的最前面的数或最后面的数移动到新数列的开头,使得新数列字典序最小.输出这个新序列. Algorithm Design 首先我们可以使用 ...
- bzoj 1640||1692: [Usaco2007 Dec]队列变换【后缀数组】
注意输出是80字符个一行!! 首先贪心很显然,就是两头尽量拿小的. 然后需要处理两头一样的情况,显然是选字典序小的一串,把数组反着接在原数组后面,然后跑sa,判断的时候直接比较rk数组 #includ ...
- BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1383 Solved: 582[Submit][St ...
- 【BZOJ1692】[Usaco2007 Dec]队列变换 后缀数组+贪心
[BZOJ1692][Usaco2007 Dec]队列变换 Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比 ...
- BZOJ1692: [Usaco2007 Dec]队列变换
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 594 Solved: 246[Submit][Sta ...
随机推荐
- 零基础入门学习Python(4)--改进我们的小游戏
前言 在以前的博客中有做个一个小游戏,但是太简单了,所以这次就来对我们做的小游戏进行改进,改善从以下四个方面进行: 程序猜错的时候要给出提示,例如告诉用户输入的值是大了还是小了. 以前程序每运行一次只 ...
- c++基础_01字串
#include <iostream> using namespace std; int main(){ for(int a=0;a<=1;a++){ for(int b=0;b&l ...
- Win2008 Server搭建FTP服务器
首先创建一个专门的FTP用户,当然也可以不创建. 用系统自带的超管用户. 设置用户名和密码.用户下次登陆必须修改密码记得去掉勾选. 在角色里面的WEB服务器找到添加角色服务.我之前有安装IIS. 没有 ...
- jmeter 接口测试
web接口测试工具: 手工测试的话可以用postman ,自动化测试多是用到 Jmeter(开源).soupUI(开源&商业版). 下面将对前一篇Postman做接口测试中的接口用Jmeter ...
- xcap发包工具的简单使用2(发送报文)
上一篇文章介绍了如何构造报文,现在简单讲一下发送报文的步骤 1.获取接口列表 点击主界面工具栏中的“刷新列表”按钮(或对应菜单“interface->Reference interfaces”) ...
- LaTex/Overleaf使用笔记
1. 添加网页引用 @misc{ r1, author = "Wikipedia", title = "Binary decision diagram --- { ...
- 【Linux】date命令用法详解(日期格式)
inux下date命令用法 date [OPTION]… [+FORMAT] date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] date命令参数 ...
- [ C++ 快速高精度模板 ] [ BigN类 ] 大整数类 高精度 模板 BigInt FFT 快速傅里叶变换
[原创 转载请注明]瞎写的,如果代码有错,或者各位大佬有什么意见建议,望不吝赐教 更新日志: 对于规模较小的整数乘法使用$$O(n^2)$$方法,提高速度 modify()和operator[]的bu ...
- 51nod1020 逆序排列
t<=10000个问,每次问n<=1000的全排列中逆序数对为k<=10000个的有多少,mod 1e9+7. 直接dp,$f(i,j)$--i的全排列中逆序数对为j的有多少,$f( ...
- POJ 2456_Aggressive cows
题意: 给定N个位置,把C头牛分别放入,求相邻两头牛的最大距离. 分析: 即为求两头牛之间最小距离的最大值.二分搜索答案. 代码: #include<iostream> #include& ...