[bzoj1692][Usaco2007 Dec]队列变换_后缀数组_贪心
队列变换 bzoj-1692 Usaco-2007 Dec
题目大意:给定一个长度为$n$的字符串。每次从头或尾取出一个字符加到另一个字符串里。要求变换后生成的字符串字典序最小,求字典序最小的字符串。
注释:$1\le n\le 3\cdot 10^4$。
想法:
考虑暴力怎么做:
每次把当前字符串左右较小的取出来。如果一样就对着往中间枚举,直到不一样为止。
这样时间复杂度为$O(n^2)$,全是一样的字符即可卡掉。
显然上述过程我们就是比较正反两个字符串谁的字典序更小对吧。
那么我们把原串翻转然后接在原串后面。两个串中间加一个非字符集字符。
对这个新串建立后缀数组然后弄在这个新串上弄两个指针。
只需要比较这两个指针对应后缀谁在$sa$中更靠前即可,因为中间有一个不可见字符隔着所以互相不会影响。
如果是前面的指针较大那就把前面的指针向后移动,反之把后面的指针向前移动。输出刚才指向的字符即可。
由于后缀数组可以将后缀排序所以只要理解了上面的暴力那么正解的正确性显然。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 60010
using namespace std;
int Ws[N],wn[N],wa[N],wb[N],n,m=28,rk[N],ht[N],r[N<<1],sa[N],wv[N],x[N],y[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_sa()
{
int i,j,p,*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;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;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++) rk[sa[i]]=i;
for(i=p=0;i<n-1;ht[rk[i++]]=p)
for(p?p--:0,j=sa[rk[i]-1];r[i+p]==r[j+p];p++);
}
int main()
{
n=rd();
int i,len=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_sa();
int j=len-1; i=0;
for(k=1;k<=len;k++)
{
if(rk[i]<rk[len+len-j]) printf("%c",r[i++]+'A'-1);
else printf("%c",r[j--]+'A'-1);
if(k%80==0) puts("");
}
return 0;
}
小结:后缀数组的本质就是把所有后缀排序。好好应用这个功能会事半功倍的啊~
[bzoj1692][Usaco2007 Dec]队列变换_后缀数组_贪心的更多相关文章
- 【BZOJ】1692 & 1640: [Usaco2007 Dec]队列变换(后缀数组+贪心)
http://www.lydsy.com/JudgeOnline/problem.php?id=1692 http://www.lydsy.com/JudgeOnline/problem.php?id ...
- [BZOJ 1692] [Usaco2007 Dec] 队列变换 【后缀数组 + 贪心】
---恢复内容开始--- 题目链接:BZOJ - 1692 题目分析 首先,有个比较简单的贪心思路:如果当前剩余字符串的两端字母不同,就选取小的字母,这样显然是正确的. 然而若两端字母相同,我们怎么选 ...
- bzoj 1640||1692: [Usaco2007 Dec]队列变换【后缀数组】
注意输出是80字符个一行!! 首先贪心很显然,就是两头尽量拿小的. 然后需要处理两头一样的情况,显然是选字典序小的一串,把数组反着接在原数组后面,然后跑sa,判断的时候直接比较rk数组 #includ ...
- bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换*&&bzoj1692[Usaco2007 Dec]队列变换*
bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换 bzoj1692[Usaco2007 Dec]队列变换 题意: 有一个奶牛队列.每次可以在原来队列的首端或是尾端牵出 ...
- BZOJ1692: [Usaco2007 Dec]队列变换
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 594 Solved: 246[Submit][Sta ...
- [bzoj1692] [Usaco2007 Dec]队列变换 (hash||暴力)
本题同bzoj1640...双倍经验双倍幸福 虽然数据范围n=3w然而O(n²)毫无压力= = http://blog.csdn.net/xueyifan1993/article/details/77 ...
- [bzoj1692][Usaco2007 Dec]队列变换——贪心+后缀数组
Brief Description 给定一个数列,您每次可以把数列的最前面的数或最后面的数移动到新数列的开头,使得新数列字典序最小.输出这个新序列. Algorithm Design 首先我们可以使用 ...
- 【BZOJ1692】[Usaco2007 Dec]队列变换 后缀数组+贪心
[BZOJ1692][Usaco2007 Dec]队列变换 Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比 ...
- BZOJ_1692_[Usaco2007 Dec]队列变换_后缀数组
BZOJ_1692_[Usaco2007 Dec]队列变换_后缀数组 Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛” ...
随机推荐
- 12.1Java-构造方法
一.构造方法 作用:在new的同时对成员变量赋值,给对象的属性初始化赋值格式:权限 方法名(参数列表){}方法的名字,必须和类的名字完全一致,大小写一致构造方法不许写返回值类型,如void,int 构 ...
- java课程设计全程实录——第2天
[反思] 今天主要完成JDBC数据的连接,查阅了大量博客和书籍,繁琐而细碎.但所幸还是连上了. [日常烦心事] 下午准备用idea连测试连接的,结果电脑跑不动....CPU一度100%居高不下,ide ...
- nginx教程从入门到精通
[转]nginx教程从入门到精通 nginx教程写了一段时间,无意中发现,nginx相关文章已经达到了近100篇了.觉得很有必要汇总到一起,它是我们运维生存时间的一片心血,他是学习nginx的同学必看 ...
- SQL优化基础 使用索引(一个小例子)
按照本文操作和体会,会对sql优化有个基本最简单的了解,其他深入还需要更多资料和实践的学习: 1. 建表: 复制代码代码如下: create table site_user ( id int IDEN ...
- 观锁和乐观锁——《POJOs in Action》
1 事务隔离 事务隔离是数据库提供的功能. SQL Server通过SET TRANSACTION ISOLATION LEVEL语句设置事务隔离级别: SET TRANSACTION ...
- 浅谈2015新版 U-Boot
过了挺长一断时间没有看U-BOOT了,这两天下载了新版的UBOOT源码(之前看的一些书都是基于早好多年的源码来讲述,总感觉心里有点不对劲,也许是我比较喜新的原因吧,不过小弟我并没有厌旧哈),好了不多扯 ...
- [转]解决右键用notepad++打开提示【ShellExecute failed (2): Is this command Correct? (Fix) 】
最近发现右键使用notepad++打开文件时提示如下错误: ShellExecute failed (2): Is this command Correct? ... 经用搜索引擎搜索得知,应该是开启 ...
- JS中二进制与十进制的相互转换
今天在做题目的时候遇到了需要十进制转换为二进制,这个我知道用toString可以,但是二进制转换为十进制我一下子就想不起来,网上搜了下,才知道是parseInt可以实现,特此记录下. 十进制转换为二进 ...
- C++ 线程同步的四种方式
程之间通信的两个基本问题是互斥和同步. (1)线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒. (2)线程互 ...
- ajax 分页点击数据缓存
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...