后缀数组 POJ 3581 Sequence
题意:把n个数字(A1比其他数字都大)的序列分成三段,每段分别反转,问字典序最小的序列。
分析:因为A1比其他数字都大,所以反转后第一段结尾是很大的数,相当是天然的分割线,第一段可以单独考虑,即求整段的字典序最小的后缀。后面两段不能分开考虑,
例子:
9
8 4 -1 5 0 5 0 2 3
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5(开始的时候我并没有复制一遍) 对应输出:0 5
第三步
3 2 0 5 对应输出: 3 2 0 5
可以看见这样做是不对的。。
必须要将剩下的字符串复制一遍贴在后面,然后再来求后缀数组。。。
正解:
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5 3 2 0 5 0 5 对应输出: 0 5 0 5;
第三步
3 2 对应输出:3 2;
所以方法是剩下的反转后+剩下的反转后组成新的串,求sa(这里不用求height,只要扫一遍即可),找到符合条件的字典序最小的后缀(应该是长度为剩下的长度的前缀)。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string> typedef long long ll;
const int N = 2e5 + 5;
int a[N];
int rev[N<<1];
int sa[N<<1], rank[N<<1];
int tmp[N<<1];
int n, k; bool cmp_sa(int i, int j) {
if (rank[i] != rank[j]) {
return rank[i] < rank[j];
} else {
int ri = i + k <= n ? rank[i+k] : -1;
int rj = j + k <= n ? rank[j+k] : -1;
return ri < rj;
}
} void get_sa(int *a, int n, int *sa) {
for (int i=0; i<=n; ++i) {
sa[i] = i;
rank[i] = i < n ? a[i] : -1;
}
for (k=1; k<=n; k<<=1) {
std::sort (sa, sa+n+1, cmp_sa);
tmp[sa[0]] = 0;
for (int i=1; i<=n; ++i) {
tmp[sa[i]] = tmp[sa[i-1]] + (cmp_sa (sa[i-1], sa[i]) ? 1 : 0);
}
for (int i=0; i<=n; ++i) {
rank[i] = tmp[i];
}
}
} void run() {
std::reverse_copy (a, a+n, rev);
get_sa (rev, n, sa);
int p1;
for (int i=0; i<n; ++i) {
p1 = n - sa[i];
if (p1 >= 1 && sa[i] >= 2) {
break;
}
}
int m = n - p1;
std::reverse_copy (a+p1, a+n, rev);
std::reverse_copy (a+p1, a+n, rev+m);
get_sa (rev, m*2, sa);
int p2;
for (int i=0; i<=m*2; ++i) {
p2 = p1 + m - sa[i];
if (p2 - p1 >= 1 && p2 < n) {
break;
}
}
std::reverse (a, a+p1);
std::reverse (a+p1, a+p2);
std::reverse (a+p2, a+n);
for (int i=0; i<n; ++i) {
printf ("%d\n", a[i]);
}
} int main() {
scanf ("%d", &n);
for (int i=0; i<n; ++i) {
scanf ("%d", a+i);
}
run ();
return 0;
}
后缀数组 POJ 3581 Sequence的更多相关文章
- [POJ 3581]Sequence
[POJ 3581]Sequence 标签: 后缀数组 题目链接 题意 给你一串序列\(A_i\),保证对于$ \forall i \in [2,n],都有A_1 >A_i$. 现在需要把这个序 ...
- POJ 3581 Sequence(后缀数组)
Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to ...
- POJ 3581 Sequence ——后缀数组 最小表示法
[题目分析] 一见到题目,就有了一个显而易见obviously的想法.只需要每次找到倒过来最小的那一个字符串翻转就可以了. 然而事情并不是这样的,比如说505023这样一个字符串,如果翻转了成为320 ...
- POJ 3581 Sequence(后缀数组)题解
题意: 已知某字符串\(str\)满足\(str_1 > max\{str_2,str_3 \cdots str_n\}\),现要求把这个字符串分成连续的三组,然后每组都翻转,问字典序最小是什么 ...
- 后缀数组 POJ 1743 Musical Theme
题目链接 题意:给定n个数字,求超过5个数字的,最长的,变化相同的,不相交的重复子串 分析:男人8题中的一题!数列相邻两项做差,形成新数列,即求数列中的最长重复子串(不可相交). 后缀数组+二分答案. ...
- 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 3261 Milk Patterns
题目链接 题意:可重叠的 k 次最长重复子串.给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠. 分析:与POJ 1743做法类似,先二分答案,height数组分段后统计 LC ...
- 后缀数组 POJ 2217 Secretary
题目链接 题意:求两个字符串的最长公共子串 分析:做法是构造新的串是两个串连接而成,中间用没有出现的字符隔开(因为这样才能保证S的后缀的公共前缀不会跨出一个原有串的范围),即newS = S + '$ ...
随机推荐
- 如何给DropDownList在后台代码中添加一个空的选项
代码如何: ddl_dept.Items.Insert(, new ListItem("---请选择---","")); new ListItem的第一个参数表 ...
- [Android Pro] root用户删除文件提示:Operation not permitted
reference to : http://blog.csdn.net/evanbai/article/details/6187578 一些文件看上去可能一切正常,但当您尝试删除的时候,居然也会报错, ...
- September 29th 2016 Week 40th Thursday
Prosperity discovers vice, adversity virtue. 得意时露瑕疵,逆境中见品质. I wish I would have someone like you, fr ...
- cuda 初学大全
转自:http://blog.csdn.net/augusdi/article/details/12529331 cuda 初学大全 1 硬件架构CUDA编程中,习惯称CPU为Host,GPU为Dev ...
- c++11的初始化
c++11 中类型初始更加方便 比如 vector<int> vec = {1,2,3}; vector<int> vec{1,2,3}; map<string, ...
- WCF分布式开发必备知识(3):Web Service 使用
参考地址:http://www.cnblogs.com/zhili/p/WebService.html 一.WebService概述 SOAP.WSDL.UDDISOAP(Simple Object ...
- 【网络资料】Astar算法详解
关于A*算法,很早就想写点什么,可是貌似天天在忙活着什么,可事实又没有做什么,真是浮躁啊!所以今晚还是来写一下总结吧! A*算法是很经典的只能启发式搜索算法,关于只能搜索算法和一般的搜索算法(例如DF ...
- 关于UltraISO打开iso文件后只有部分文件问题
背景:在安装CentOS 7的时候,用UltraISO打开之后,只有一个EFI文件,刻完U盘,却无法引导. 之前还以为偶没下载全,就又下了一遍,还好偶搞得的NetInstall,要不然就呵呵了. 解决 ...
- map[C++]
//map是一个存储键值对的容器,也是一个双向链表 #include <iostream> using namespace std; #include <map> int ma ...
- C# 指针操作图像 二值化处理
/// <summary> /// 二值化图像 /// </summary> /// <param name="bmp"></param& ...