【题目链接】 http://poj.org/problem?id=3581

【题目大意】

  给出一个数列,将这个数列分成三段,每段分别翻转,使得其字典序最小,输出翻转后的数列。

【题解】

  首先,第一个翻转点就是翻转后数列的最小后缀,注意由于一定要分成三段,则至少要剩下两个元素。难点主要是如何处理第二个翻转点,我们发现剩余的部分的每一种翻转拆分都是将两串翻转后剩余部分拼接在一起得到的串的子串,所以我们将剩余部分翻转,复制一份拼接在后面,求最小后缀即可。

【代码】

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N=800010;
int n,rank[N],sa[N],h[N],tmp[N],cnt[N],ans; int s[N];
void suffixarray(int n,int m){
int i,j,k;n++;
for(i=0;i<2*n+5;i++)rank[i]=sa[i]=h[i]=tmp[i]=0;
for(i=0;i<m;i++)cnt[i]=0;
for(i=0;i<n;i++)cnt[rank[i]=s[i]]++;
for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
for(i=0;i<n;i++)sa[--cnt[rank[i]]]=i;
for(k=1;k<=n;k<<=1){
for(i=0;i<n;i++){
j=sa[i]-k;
if(j<0)j+=n;
tmp[cnt[rank[j]]++]=j;
}sa[tmp[cnt[0]=0]]=j=0;
for(i=1;i<n;i++){
if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k])cnt[++j]=i;
sa[tmp[i]]=j;
}memcpy(rank,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if(j>=n-1)break;
}for(j=rank[h[i=k=0]=0];i<n-1;i++,k++)
while(~k&&s[i]!=s[sa[j-1]+k])h[j]=k--,j=rank[sa[j]+1];
}
int disc[N];
int remark(int x){
int l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
if(disc[mid]<x)l=mid+1;
else if(disc[mid]==x)return mid;
else r=mid-1;
}
}
int a[N],p1,p2;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",a+i),disc[i+1]=a[i];
sort(disc+1,disc+n+1);
for(int i=0;i<n;i++)a[i]=remark(a[i]);
reverse_copy(a,a+n,s);
suffixarray(n,n+1);
for(int i=0;i<=n;i++){p1=n-sa[i];if(p1>=1&&n-p1>=2)break;}
int m=n-p1;
reverse_copy(a+p1,a+n,s);
reverse_copy(a+p1,a+n,s+m);
suffixarray(m<<1,n+1);
for(int i=0;i<=2*m;i++){p2=p1+m-sa[i];if(p2>p1&&n>p2)break;}
reverse(a,a+p1);reverse(a+p1,a+p2);reverse(a+p2,a+n);
for(int i=0;i<n;i++)printf("%d\n",disc[a[i]]);
return 0;
}

  

POJ 3581 Sequence(后缀数组)的更多相关文章

  1. POJ 3581 Sequence(后缀数组)

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

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

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

  3. POJ 3581 Sequence [后缀数组]

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

  4. [POJ 3581]Sequence

    [POJ 3581]Sequence 标签: 后缀数组 题目链接 题意 给你一串序列\(A_i\),保证对于$ \forall i \in [2,n],都有A_1 >A_i$. 现在需要把这个序 ...

  5. 后缀数组 POJ 3581 Sequence

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

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

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

  7. POJ3581 Sequence —— 后缀数组

    题目链接:https://vjudge.net/problem/POJ-3581 Sequence Time Limit: 5000MS   Memory Limit: 65536K Total Su ...

  8. POJ 2406 KMP/后缀数组

    题目链接:http://poj.org/problem?id=2406 题意:给定一个字符串,求由一个子串循环n次后可得到原串,输出n[即输出字符串的最大循环次数] 思路一:KMP求最小循环机,然后就 ...

  9. POJ 1743-POJ - 3261~后缀数组关于最长字串问题

    POJ 1743 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1~~88范围内的整数,现在要找一个重复的主题.“主题”是整个音符序列的一个子串,它需 ...

  10. POJ - 1226 Substrings (后缀数组)

    传送门:POJ - 1226 这个题跟POJ - 3294  和POJ - 3450 都是一样的思路,一种题型. POJ - 3294的题解可以见:https://www.cnblogs.com/li ...

随机推荐

  1. JVM学习之常用概念

    方法区     当JVM使用类装载器装载某个类时,它首先要定位对应的class文件,然后读入这个class文件,最后,JVM提取该文件的内容信息,并将这些信息存储到方法区,最后返回一个class实例. ...

  2. 实现php获取mp3文件元信息如播放时间歌曲作者等

    最近收集到一个php获取mp3文件元信息的类,感觉比较方便.现在分享给大家! 下面是使用方式和测试方式: <?php include_once 'mp3file.class.php'; func ...

  3. abstract的方法是否可同时是static 是否可同时是native 是否可同时

    搬一下以前写的 1.abstract与static (what)​ abstract:用来声明抽象方法,抽象方法没有方法体,不能被直接调用,必须在子类overriding后才能使用 static:用来 ...

  4. Android Studio git ignore

    # Built application files *.apk *.ap_ # Files for the Dalvik VM *.dex # Java class files *.class # G ...

  5. Javascript 匀速运动停止条件——逐行分析代码,让你轻松了解运动的原理

    我们先来看下之前的匀速运动的代码,修改了速度speed后会出现怎么样的一个bug.这里加了两个标杆用于测试 <style type="text/css"> #div1 ...

  6. 简单的实现树莓派的WEB控制

    最终效果如图: 用到的知识:Python Bottle HTML Javascript JQuery Bootstrap AJAX 当然还有 linux 我去,这么多--我还是一点一点说起吧-- 先贴 ...

  7. vb6.0 时间日期

    使用year(now)可以得到4位数的年    你还可以用Format来得到, 还有FormatDateTime 下面两种都是一样的结果:  FormatDateTime(now,vbLongDate ...

  8. Linux内核中的list用法和实现分析

    这些天在思考知识体系的完整性,发现总是对消息队列的实现不满意,索性看看内核里面的链表实现形式,这篇文章就当做是学习的i笔记吧.. 内核代码中有很多的地方使用了list,而这个list的用法又跟我们平时 ...

  9. Java String 和 StringBuffer的区别

    1.String类的定义是这样的: public final class String extends Object implements   Serializable, Comparable< ...

  10. OSG中的视角 eye up center

    这三个值都是vec3变量,其中eye和center确定视角         eye就相当于人的眼睛,我们观察场景,是从这个坐标去看的,然后有了眼睛,我们观察得有一个方向,那么久需要另外一个坐标,就是c ...