题目链接:点击查看

题目大意:给出一个数列,保证第一个数一定大于其余的所有数,现在需要让我们将其分为连续的三段,每一段独立反转后保证字典序最小,题目要求输出反转后字典序最小的数列

题目分析:因为第一个数一定大于其余的所有数,所以将整个数列反转后,求排名最小的后缀数组就是第一段的答案了,因为这个性质保证了反转后的数组中最后一个数是最大的,肯定不可能是以最后一个数字为开头的后缀,只可能是以前面的数字为开头的后缀,包含了最后一个数字,所以保证了答案的正确性,那么剩下第二段和第三段该如何分割呢,网上都说了正解的方法,但却没说明白为什么,正解就是在反转后的数列中,去掉已经确定好的第一段后,将剩余的数列复制一遍,然后求后缀数组,通过sa来确定排名最小的后缀就是答案了,为什么可以这样做呢,因为在去掉第一段后的开头已经不能保证是最大的了,也就不满足上面所说的性质了,但是仔细考虑一下,我们需要将剩下的字符串分成两段并分别反转,那么意味着反转后复制一下,在前半段的每个后缀都代表了以每个字母为断点反转后的答案了,这个时候就可以直接比较这些后缀的大小,选出排名最小的那个后缀就是本题的答案了

注意,数字的范围题目没给出,我看网上大部分代码都是将原模板中的桶排序替换为了sort,我感觉不妥,为什么不直接离散化呢,一开始我也是固执的不想用离散化,但是自己main函数里写的已经验证过很多次是没有问题的了,交上去还是WA,没办法向离散化妥协,改完离散化后立马AC,不得不说不能乱用别人的模板,出了错误都不知道是哪里出的

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<ctime>
#include<climits>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e5+100;int sa[N]; //SA数组,表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[N],t2[N],c[N],a[N];int s[N],len;vector<int>v;void build_sa(int s[],int n,int m)//n为添加0后的总长
{int i,j,p,*x=t1,*y=t2;for(i=0;i<m;i++) c[i]=0;for(i=0;i<n;i++) c[x[i]=s[i]]++;for(i=1;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;for(j=1;j<=n;j<<=1) {p=0;for(i=n-j;i<n;i++) y[p++]=i;for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;for(i=0;i<m;i++) c[i]=0;for(i=0;i<n;i++) c[x[y[i]]]++;for(i=1;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];swap(x,y);p=1,x[sa[0]]=0;for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;if(p>=n) break;m=p;}
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int n,cut1,cut2;//找出两个断点后最后统一输出scanf("%d",&n);len=n;for(int i=0;i<n;i++){scanf("%d",a+i);v.push_back(a[i]);}sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());for(int i=0;i<n;i++)a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;for(int i=n-1;i>=0;i--)s[i]=a[n-i-1];s[len]=0;build_sa(s,len+1,v.size()+1);int pos=0;for(int i=1;i<=len;i++){if(sa[i]>=2){cut1=len-sa[i];break;}}len=0;for(int i=n-1;i>=cut1;i--)s[len++]=a[i];for(int i=n-1;i>=cut1;i--)s[len++]=a[i];s[len]=0;build_sa(s,len+1,v.size()+1);for(int i=1;i<=len;i++){if(sa[i]>=1&&sa[i]<len/2){cut2=cut1+len/2-sa[i];break;}}reverse(a,a+cut1);reverse(a+cut1,a+cut2);reverse(a+cut2,a+n);for(int i=0;i<n;i++)printf("%d\n",v[a[i]-1]);return 0;
}

POJ - 3581 Sequence(后缀数组)相关推荐

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

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

  2. POJ 3415 (后缀数组)

    被虐残了T_T.开始没思路,膜拜大牛的思路又看不懂...推荐一个题解:http://hi.baidu.com/fpkelejggfbfimd/item/5c76cfcba28fba26e90f2ea6 ...

  3. POJ 2217 Secretary (后缀数组)

    原题链接 Problem Description The basic condition of success of a political party, it is the good Electio ...

  4. POJ 2217 Secretary (后缀数组,挑战程序)

    题目意思: 给出两个字符串,要求两个字符串最长的公共子串(是子串不是子序列) 挑战程序设计竞赛, 383 页 本题要点: 1.高度数组,lcp[i] 表示后缀数组中,第i个字符串 S[sa[i] -] ...

  5. POJ - 1226 Substrings(后缀数组+二分)

    题目链接:点击查看 题目大意:给出n个字符串,求出n个字符串中或者在他们翻转过来的字符串中,出现的最长公共子串的长度 题目分析:说白了就是求n个字符串中的最长公共子串的变形,而这个变形也相当简单,只是 ...

  6. Musical Theme POJ - 1743(后缀数组+二分)

    求不可重叠最长重复子串 对于height[i]定义为sa[i]和 sa[i-1]的最长公共前缀 这个最长公共前缀的值肯定是最大的 证明: 设rank[j] < rank[k], 则不难证明后缀j ...

  7. poj 3261 后缀数组 找反复出现k次的子串(子串能够重叠)

    题目:http://poj.org/problem?id=3261 仍然是后缀数组的典型应用----后缀数组+lcp+二分 做的蛮顺的,1A 可是大部分时间是在调试代码.由于模板的全局变量用混了,而自 ...

  8. poj 3261 Milk Patterns 后缀数组 最长重复子串

    http://poj.org/problem?id=3261 给一串数组,数组最少含有k个相同子串,可重叠,求这样子串的最长长度. 后缀数组求出 height[],若连续k个height[]都大于mi ...

  9. POJ 1743 (后缀数组+不重叠最长重复子串)

    题目链接: http://poj.org/problem?id=1743 题目大意:楼教主の男人八题orz.一篇钢琴谱,每个旋律的值都在1~88以内.琴谱的某段会变调,也就是说某段的数可以加减一个旋律 ...

最新文章

  1. VMware 虚拟机的虚拟磁盘编程知识点扫盲之二
  2. MySQL 使用explain查看执行计划
  3. 第二十五期:知乎用Go替代Python,说明了啥
  4. Oracle存储过程(转)
  5. vijos P1001 谁拿了最多奖学金
  6. python const char_python C 扩展(转载)
  7. 关于vscode软件更换软件背景的问题
  8. 小猫爬山题解(暴力解题)
  9. markdown语法手册完整版
  10. Android-第十三节04Room框架详解
  11. excel文件类型自动判断
  12. 【Linux】命令别名与历史命令(alise\history)
  13. Android 插件仓库
  14. 将ppm格式转换为bmp格式的方式有哪些?
  15. 关于CPU 和 GPU
  16. 最大公约数几种算法分析
  17. matlab跳动的心脏,Matlab绘制跳动的心
  18. MapReduce任务卡在Running Job状态的多种解决方法
  19. 87个C#帮助类,各种功能性代码(转载自微信公众号:dotNET全栈开发)
  20. VS 2017经常出现打不开问题

热门文章

  1. linux 源码 在线浏览,Linux下实现文档在线浏览
  2. SpringCloud环境搭建
  3. feign如何使用?
  4. Protobuf序列化的原理-负数的存储
  5. 观察者模式的应用场景
  6. OAuth2.0授权码认证流程介绍
  7. HelloWorld程序的代码编写
  8. ES6新特性之函数优化-箭头函数
  9. Response_案例1_路径_相对路径
  10. 字符串的构造方法和直接创建