[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的更多相关文章

  1. POJ 3581 Sequence(后缀数组)

    [题目链接] http://poj.org/problem?id=3581 [题目大意] 给出一个数列,将这个数列分成三段,每段分别翻转,使得其字典序最小,输出翻转后的数列. [题解] 首先,第一个翻 ...

  2. POJ 3581 Sequence [后缀数组]

    Sequence Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6911   Accepted: 1543 Case Tim ...

  3. POJ 3581 Sequence(后缀数组)

    Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An,  you are to ...

  4. 后缀数组 POJ 3581 Sequence

    题目链接 题意:把n个数字(A1比其他数字都大)的序列分成三段,每段分别反转,问字典序最小的序列. 分析:因为A1比其他数字都大,所以反转后第一段结尾是很大的数,相当是天然的分割线,第一段可以单独考虑 ...

  5. POJ 3581 Sequence ——后缀数组 最小表示法

    [题目分析] 一见到题目,就有了一个显而易见obviously的想法.只需要每次找到倒过来最小的那一个字符串翻转就可以了. 然而事情并不是这样的,比如说505023这样一个字符串,如果翻转了成为320 ...

  6. POJ 3581 Sequence(后缀数组)题解

    题意: 已知某字符串\(str\)满足\(str_1 > max\{str_2,str_3 \cdots str_n\}\),现要求把这个字符串分成连续的三组,然后每组都翻转,问字典序最小是什么 ...

  7. POJ 3581:Sequence(后缀数组)

    题目链接 题意 给出n个数字的序列,现在让你分成三段,使得每一段翻转之后拼接起来的序列字典序最小.保证第一个数是序列中最大的数. 例如样例是{10, 1, 2, 3, 4},分成{1, 10}, {2 ...

  8. Sequence POJ - 3581 后缀数组

    题意: 将一个序列分成非空的三部分,将每部分翻转后组合成一个新的序列, 输出这样操作得到的序列中字典序最小的序列 (保证第一个数是数组中最大的元素) 题解: 把数组当作串串. 因为第一个数最大,所以我 ...

  9. POJ 2442 Sequence

    Pro. 1 给定k个有序表,取其中前n小的数字.组成一个新表,求该表? 算法: 由于  a1[1] < a1[2] < a1[3] ... <a1[n] a2[1] < a2 ...

随机推荐

  1. 基于FPGA的HDMI高清显示接口驱动

    HDMI是(High Definition Multimedia Interface)的缩写,意思是高清晰度多媒体接口,是一种数字化视频/音频接口技术,适合影像传输的专用型数字化接口,可同时传送音频和 ...

  2. -pie can only be used when targeting iOS 4.2 or later错误解决

    在工程的build setting里,把IPHONEOS_DEPLOYMENT_TARGET改成4.2或以上就行了

  3. DALI调色温

    DALI调色温模块使用手册 公  司: 深圳市万秀电子有限公司 网  站: http://www.wanxiucx.com 总  机: 0755-23215689 联系人: 张先生 手  机: 139 ...

  4. Oracle问题之ORA-01031权限不足

    Oracle问题之ORA-01031权限不足 此时应该按照如下写: sqlplus /nolog conn / as sysdba shutdown immediate 本地以sysdba身份登录数据 ...

  5. Android 双卡获取当前使用流量在线卡的信息

    最近接触了一个项目,需要获取在线流量卡的信息,下面的方式,可以获取大部分手机的正确手机卡信息. 一  获取获取IMEI public static String getDeviced(int solt ...

  6. linux_常用命令_2

    rev 反向读取, reverse echo 123456 | rev # 结果为 654321 rev Name.txt # 行号没变,每一行的数据翻转过来 less 具有more命令所有功能,更加 ...

  7. JavaScript数组的22种方法

    原文:http://www.cnblogs.com/xiaohuochai/p/5682621.html javascript中数组的22种方法   前面的话 数组总共有22种方法,本文将其分为对象继 ...

  8. pulltorefresh 设置刷新文字提示颜色

     xmlns:ptr="http://schemas.android.com/apk/res-auto" 赵泽民 2016/7/12 15:48:58 ptr:ptrHeaderS ...

  9. WebView加载html5页面

    mWebView = (WebView) findViewById(R.id.mwebview); mWebView.getSettings().setJavaScriptEnabled(true); ...

  10. RecyclerView用法

    主界面布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...