[POJ 3581]Sequence
[POJ 3581]Sequence
标签: 后缀数组
题意
给你一串序列\(A_i\),保证对于$ \forall i \in [2,n],都有A_1 >A_i$。
现在需要把这个序列分成三段,并且将这三段分别翻转,求如何翻转使整个序列字典序最小。(每一段不能为空)
题解
首先可以确定第一段的位置。
注意到,\(A_1\)是最大的,所以我们就只用考虑怎样找到一个前缀使其翻转后的字典序最小。
(假如不是的话,就可能找到两个前缀翻转之后,一个为另一个的前缀,无法解决)
这等价于翻转之后找到一个后缀使其字典序最小,用后缀数组处理一下。
然后确定第二段的位置。
先翻转之后,找一个分割点使整个串最小。这等价于最小循环表示法问题。
可以直接用后缀数组解决,也有O(n)的做法。
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=0,p=1;char ch=getchar();
while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
if(ch=='-')p=-1,ch=getchar();
while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum*p;
}
const int maxn=4e5+20;
int n,a[maxn],sa[maxn],S[maxn],cnt;
void init()
{
n=read();
REP(i,0,n-1)a[i]=read(),S[cnt++]=a[i];
sort(S,S+cnt);
cnt=unique(S,S+cnt)-S;
REP(i,0,n-1)a[i]=lower_bound(S,S+cnt,a[i])-S;
}
int r[maxn*2];
int x[maxn],y[maxn]={0},bug[maxn]={0},v[maxn*2];
void suffix_array(int *r,int n)
{
int p=0,m=200000;
memset(v,-1,sizeof(v));
REP(i,0,m)bug[i]=0;
REP(i,0,n-1)bug[x[i]=r[i]]++;
REP(i,1,m)bug[i]+=bug[i-1];
DREP(i,n-1,0)sa[--bug[x[i]]]=i;
for(int j=1;p<n;j*=2,m=p)
{
p=0;REP(i,n-j,n-1)y[p++]=i;
REP(i,0,n-1)if(sa[i]>=j)y[p++]=sa[i]-j;
REP(i,0,m)bug[i]=0;
REP(i,0,n-1)bug[v[i]=x[y[i]]]++;
REP(i,1,m)bug[i]+=bug[i-1];
DREP(i,n-1,0)sa[--bug[v[i]]]=y[i];
REP(i,0,n-1)v[i]=x[i];p=1;x[sa[0]]=0;
REP(i,1,n-1)x[sa[i]]=v[sa[i-1]]==v[sa[i]] && v[sa[i-1]+j]==v[sa[i]+j] ?p-1:p++;
}
}
void doing()
{
REP(i,0,n-1)r[i]=a[n-i-1];
suffix_array(r,n);
int X=0;
REP(i,0,n-1)if(sa[i]>1){X=sa[i];break;}
REP(i,X,n-1)cout<<S[r[i]]<<endl;
//REP(i,0,n-X-1)x[i]=a[i+X+1];
n=X;
REP(i,n,2*n-1)r[i]=r[i-n];
suffix_array(r,2*n);
REP(i,0,2*n-1)if(sa[i]<n && sa[i]){X=sa[i];break;}
REP(i,X,n-1+X)cout<<S[r[i]]<<endl;
}
int main()
{
init();
doing();
return 0;
}
[POJ 3581]Sequence的更多相关文章
- POJ 3581 Sequence(后缀数组)
[题目链接] http://poj.org/problem?id=3581 [题目大意] 给出一个数列,将这个数列分成三段,每段分别翻转,使得其字典序最小,输出翻转后的数列. [题解] 首先,第一个翻 ...
- POJ 3581 Sequence [后缀数组]
Sequence Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6911 Accepted: 1543 Case Tim ...
- POJ 3581 Sequence(后缀数组)
Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to ...
- 后缀数组 POJ 3581 Sequence
题目链接 题意:把n个数字(A1比其他数字都大)的序列分成三段,每段分别反转,问字典序最小的序列. 分析:因为A1比其他数字都大,所以反转后第一段结尾是很大的数,相当是天然的分割线,第一段可以单独考虑 ...
- POJ 3581 Sequence ——后缀数组 最小表示法
[题目分析] 一见到题目,就有了一个显而易见obviously的想法.只需要每次找到倒过来最小的那一个字符串翻转就可以了. 然而事情并不是这样的,比如说505023这样一个字符串,如果翻转了成为320 ...
- POJ 3581 Sequence(后缀数组)题解
题意: 已知某字符串\(str\)满足\(str_1 > max\{str_2,str_3 \cdots str_n\}\),现要求把这个字符串分成连续的三组,然后每组都翻转,问字典序最小是什么 ...
- POJ 3581:Sequence(后缀数组)
题目链接 题意 给出n个数字的序列,现在让你分成三段,使得每一段翻转之后拼接起来的序列字典序最小.保证第一个数是序列中最大的数. 例如样例是{10, 1, 2, 3, 4},分成{1, 10}, {2 ...
- Sequence POJ - 3581 后缀数组
题意: 将一个序列分成非空的三部分,将每部分翻转后组合成一个新的序列, 输出这样操作得到的序列中字典序最小的序列 (保证第一个数是数组中最大的元素) 题解: 把数组当作串串. 因为第一个数最大,所以我 ...
- POJ 2442 Sequence
Pro. 1 给定k个有序表,取其中前n小的数字.组成一个新表,求该表? 算法: 由于 a1[1] < a1[2] < a1[3] ... <a1[n] a2[1] < a2 ...
随机推荐
- 微软Azure AspNetCore微服务实战第2期
2018年1月28日,虽然上海的大雪在城区已经见不到踪影,但还是很冷.不过天气再冷,也阻止不了小伙伴参加活动的热情. 感谢王振,苏老师以及微软Azure API Management的产品经理Alvi ...
- NSDateFormatter相关整理
//实例化一个NSDateFormatter对象NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init]; //设定时间格式,这里可 ...
- CentOS7中使用iptables
原文地址:http://blog.csdn.net/u012486840/article/details/53161555 1.关闭firewall: systemctl stop firewalld ...
- python3 第五章 - 什么是变量、运算符、表达式
在读这一章时,运算符的内容比较多,不要去死记.现在记不住也没有关系,现在只要有这个印象.在后面的学习中,会慢慢加深理解,在理解中去记就容易得多了 1.变量 什么是变量?通俗的讲,就是存储在内存中可以变 ...
- c:if true、false都显示
看了半天,最后发现jstl标签库没有引入! <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core ...
- java利用poi生成/读取excel表格
1.引入jar包依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi< ...
- PHP 运行 php-fpm 报错
报错如下: [27-Aug-2017 18:34:23] WARNING: Nothing matches the include pattern '/usr/local/php/etc/php- ...
- java 中字符串比较equals()和equalsIgnoreCase()的区别
1.使用equals( )方法比较两个字符串是否相等 boolean equals(Object str) 这里str是一个用来与调用字符串(String)对象做比较的字符串(String)对象. 如 ...
- ProgressDialog的使用及逻辑处理
一般用的情况先声明一个ProgressDialog progressShow = true;(用来判断用户是否点击了取消键) final ProgressDialog pd = new Progres ...
- CSS 自动隐藏文字并添加省略号
.cut { overflow:hidden; white-space:nowrap; text-overflow:ellipsis; -o-text-overflow:ellipsis; -icab ...