BZOJ 1692: [Usaco2007 Dec]队列变换 (后缀数组/二分+Hash)
跟BZOJ 4278: [ONTAK2015]Tasowanie一模一样
SA的做法就是把原串倒过来接在原串后面,O(nlogn)O(nlogn)O(nlogn)做后缀数组,就能O(1)O(1)O(1)够比较每个前缀和后缀谁的字典序小了.
Hash二分也可以.
CODE(SA)
O(nlogn)O(nlogn)O(nlogn)
#include<bits/stdc++.h>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 60005;
int s[MAXN];
int x[MAXN], y[MAXN], c[MAXN], rk[MAXN], sa[MAXN];
inline void Get_Sa(int n, int m) {
for(int i = 1; i <= n; ++i) ++c[x[i]=s[i]];
for(int i = 2; i <= m; ++i) c[i] += c[i-1];
for(int i = n; i >= 1; --i) sa[c[x[i]]--] = i;
for(int k = 1; k <= n; k<<=1) {
int p = 0;
for(int i = n-k+1; i <= n; ++i) y[++p] = i;
for(int i = 1; i <= n; ++i) if(sa[i]>k) y[++p] = sa[i]-k;
for(int i = 1; i <= m; ++i) c[i] = 0;
for(int i = 1; i <= n; ++i) ++c[x[i]];
for(int i = 2; i <= m; ++i) c[i] += c[i-1];
for(int i = n; i >= 1; --i) sa[c[x[y[i]]]--] = y[i];
swap(x, y);
x[sa[1]] = p = 1;
for(int i = 2; i <= n; ++i)
x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k]) ? p : ++p;
if((m=p) == n) break;
}
for(int i = 1; i <= n; ++i) rk[sa[i]] = i;
}
int n;
int main() {
read(n); char ch;
for(int i = 1; i <= n; ++i) {
while(!isalpha(ch=getchar()));
s[i] = ch-'A'+1;
}
for(int i = 1; i <= n; ++i) s[(n<<1)-i+1] = s[i];
Get_Sa(n<<1, 26);
int l = 1, r = n, tot = 0;
while(l <= r)
if(rk[l] < rk[(n<<1)-r+1]) { putchar(s[l++]+'A'-1); if(++tot == 80) tot = 0, putchar('\n'); }
else { putchar(s[r--]+'A'-1); if(++tot == 80) tot = 0, putchar('\n'); }
}
CODE(Hash)
从学长那里搬运来的代码(跑得比后缀数组快)
O(nlogn)O(nlogn)O(nlogn)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ull unsigned int
using namespace std;
const int maxn=30003;
char s[maxn];
ull pre[maxn],jc[maxn],val1,val2,pre1[maxn];
short i,j,k,n,m,l,r,mid,len,L,R;
inline short getlen(){
if(s[L]!=s[R])return 0;
l=1;r=R-L+1;
if(pre[L+r-1]-pre[L-1]*jc[r]==pre1[R-r+1]-pre1[R+1]*jc[r])return r;r--;
while(l<r){
mid=(l+r+1)>>1;
val1=pre[L+mid-1]-pre[L-1]*jc[mid];
val2=pre1[R-mid+1]-pre1[R+1]*jc[mid];
if(val1!=val2)r=mid-1;else l=mid;
if(s[L+l]!=s[R-l])return l;
}
return l;
}
inline bool bigger(){
if(s[L]!=s[R])return s[L]>s[R];
len=getlen();
if(len==R-L+1)return 1;
else return s[L+len]>s[R-len];
}
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++)for(s[i]=getchar();s[i]<'A'||s[i]>'Z';s[i]=getchar());
jc[0]=1;for(i=1;i<=n;i++)jc[i]=jc[i-1]*107;
for(i=1;i<=n;i++)pre[i]=pre[i-1]*107+(ull)s[i]-'A';
for(i=n;i;i--)pre1[i]=pre1[i+1]*107+(ull)s[i]-'A';
L=1;R=n;
for(i=1;i<=n;i++)if(bigger()){
putchar(s[R--]);
if(i%80==0)putchar('\n');
}else {putchar(s[L++]);if(i%80==0)putchar('\n');}
return 0;
}
BZOJ 1692: [Usaco2007 Dec]队列变换 (后缀数组/二分+Hash)的更多相关文章
- BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1383 Solved: 582[Submit][St ...
- 1692: [Usaco2007 Dec]队列变换|后缀数组|贪心
将字符串翻转后接到原串的后面,中间加一个分隔符,每次都贪心选择rankrank小的那个 事实上就是练习一发后缀数组的模板 #include<algorithm> #include<i ...
- BZOJ 1692: [Usaco2007 Dec]队列变换( 贪心 )
数据 n <= 30000 , 然后 O( n² ) 的贪心也过了..... USACO 数据是有多弱啊 = = ( ps : BZOJ 1640 和此题一模一样 , 双倍经验 ) ------ ...
- 【BZOJ1692】[Usaco2007 Dec]队列变换 后缀数组+贪心
[BZOJ1692][Usaco2007 Dec]队列变换 Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比 ...
- [BZOJ 1692] [Usaco2007 Dec] 队列变换 【后缀数组 + 贪心】
---恢复内容开始--- 题目链接:BZOJ - 1692 题目分析 首先,有个比较简单的贪心思路:如果当前剩余字符串的两端字母不同,就选取小的字母,这样显然是正确的. 然而若两端字母相同,我们怎么选 ...
- ●BZOJ 1692 [Usaco2007 Dec]队列变换
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1692 题解: 后缀数组,贪心由于每次可以取出旧队列的首部或尾部放在新队列的尾部.所以就需要比 ...
- BZOJ 1692: [Usaco2007 Dec]队列变换
Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的"全美农场主大奖赛".在这场比赛中,每个参赛者都必须让他的奶牛排成一列 ...
- bzoj:1692 [Usaco2007 Dec]队列变换&&1640 [Usaco2007 Nov]Best Cow Line 队列变换
Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席 ...
- bzoj 1692: [Usaco2007 Dec]队列变换 ——二分+hash
Description FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”.在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席 ...
随机推荐
- airflow_failover启动scheduler
参考: https://github.com/teamclairvoyant/airflow-scheduler-failover-controller 1.stop failover2.stop s ...
- linux下vi编辑器常用命令
最近折腾云主机centOS,不得不接触到各种命令,特别是vi编辑器. 时常悔恨当时没好好听金老伯的linux课,导致现在操作命令用的十分生疏,甚至跳转行首行尾都要查一查才知道. 所以〒▽〒有了下面这篇 ...
- java注解类型的aop
import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import org.aspectj.la ...
- Dijkstra(模板)
#define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include <cstdio>//sprintf islower isupp ...
- 后缀数组 LCP--模板题
题意: 给你S串和T串,用T串的所有前缀去匹配S串(匹配值是最长公共子串). 问你总值相加是多少. 思路: 先把两个S,T串倒过来,再拼接 S#T 合成一串,跑一下后缀数组 在排序好的rank里计算每 ...
- HashMap的四种遍历方式
package com.xt.map; import java.util.HashMap; import java.util.Iterator; import java.util.Map; impor ...
- React学习——子组件给父组件传值
//子组件 var Child = React.createClass({ render: function(){ return ( <div> 请输入邮箱:<input onCha ...
- vue源码分析
1.new Vue的过程 1)首先Vue是一个类,初始化时已经添加很多 initMixin(Vue) 给原型添加Vue.prototype._init stateMixin( ...
- Spring MVC之@RequestParam @RequestBody @RequestHeader 等详
Spring MVC之@RequestParam @RequestBody @RequestHeader 等详 引言: 接上一篇文章,对@RequestMapping进行地址映射讲解之后,该篇 ...
- Hadoop入门到实战全套大数据Hadoop学习视频
资料获取方式,关注公总号RaoRao1994,查看往期精彩-所有文章或者后台回复[Hadoop]获取,即可获取资源下载链接 更多资源获取,请关注公总号RaoRao1994