POJ 3581 Sequence ——后缀数组 最小表示法
【题目分析】
一见到题目,就有了一个显而易见obviously的想法。只需要每次找到倒过来最小的那一个字符串翻转就可以了。
然而事情并不是这样的,比如说505023这样一个字符串,如果翻转了成为320505.
最小的后缀是05,那么得到的字符串是055023,然而最小的结果是全部翻转,为050523.
因为我们没有考虑到翻转后的字符和未翻转的字符有可能会连接起来,我们并没有考虑到连接部分对答案的影响。
这里我们用最小表示的方法来做这道题目,每次操作完成之后,都需要把翻转后的串复制两遍,这样的话,我们找到在复制的第一遍中的最小的后缀输出。
这样子我们就可以考虑到他本身的翻转和不翻转的部分组成的字符串的大小。
上面的方法就是后缀数组,复制两次的方法其实就是为了求最小表示的开头,为O(nlogn)。
所以我们可以直接用最小表示法来做,而且不需要复制,最小表示法是O(n)的,直接扫一遍就可以得到最小表示的起始位置,然后输出即可。
这样就有了两种方法。
然而人比较懒,练练后缀数组好了。
注意边界的条件(第一次翻转最少剩下两个字符,为后面两次翻转留下空间)。
【代码】
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib> #include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm> using namespace std; #define maxn 800005
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i) void Finout()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
} int Getint()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
} int n,a[maxn],b[maxn],top; struct SuffixArray{
int s[maxn];
int tmp[maxn],cnt[maxn],sa[maxn],rk[maxn],h[maxn];
void build(int n,int m)
{
int i,j,k;n++;
F(i,0,2*n+5) tmp[i]=sa[i]=rk[i]=h[i]=0;
F(i,0,m-1) cnt[i]=0;
F(i,0,n-1) cnt[rk[i]=s[i]]++;
F(i,1,m-1) cnt[i]+=cnt[i-1];
F(i,0,n-1) sa[--cnt[rk[i]]]=i;
// cout<<" ";F(i,0,n) cout<<b[s[i]]<<" ";cout<<endl;
for (k=1;k<=n;k<<=1)
{
F(i,0,n-1)
{
j=sa[i]-k;
if (j<0) j+=n;
tmp[cnt[rk[j]]++]=j;
}
sa[tmp[cnt[0]=0]]=j=0;
F(i,1,n-1)
{
if (rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k]) cnt[++j]=i;
sa[tmp[i]]=j;
}
memcpy(rk,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if (j>=n-1) break;
}
// cout<<"SA ";F(i,0,n) cout<<sa[i]<<" ";cout<<endl;
// for (j=rk[h[i=k=0]=0];i<n-1;++i,++k)
// while (~k&&s[i]!=s[sa[j-1]+k]) h[j]=k--,j=rk[sa[j]+1];
// cout<<"height ";F(i,0,n) cout<<h[i]<<" "; cout<<endl;
}
}arr; int main()
{
Finout();
n=Getint();
F(i,0,n-1) a[i]=Getint(),b[i]=a[i];
b[n]=-inf;
sort(b,b+n+1);
top=unique(b,b+n+1)-b;
F(i,0,n-1) a[i]=lower_bound(b,b+top,a[i])-b;
F(i,0,n-1) arr.s[n-1-i]=a[i];
arr.s[n]=0;
arr.build(n-1,2005);
// cout<<"build over"<<endl;
int tmp=0;
while (arr.sa[tmp]<2||arr.sa[tmp]>=n) tmp++;
F(i,arr.sa[tmp],n-1) cout<<b[arr.s[i]]<<endl;// cout<<endl;
n-=n-arr.sa[tmp];
F(i,0,n-1) arr.s[i+n]=arr.s[i];
arr.s[2*n]=0;
arr.build(2*n-1,2005);
tmp=0; while (arr.sa[tmp]<1||arr.sa[tmp]>=n) tmp++;
F(i,arr.sa[tmp],n-1) cout<<b[arr.s[i]]<<endl; //cout<<endl;
F(i,0,arr.sa[tmp]-1) cout<<b[arr.s[i]]<<endl; //cout<<endl;
}
POJ 3581 Sequence ——后缀数组 最小表示法的更多相关文章
- POJ 3581 Sequence(后缀数组)
Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to ...
- POJ 3581 Sequence [后缀数组]
Sequence Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6911 Accepted: 1543 Case Tim ...
- [POJ 3581]Sequence
[POJ 3581]Sequence 标签: 后缀数组 题目链接 题意 给你一串序列\(A_i\),保证对于$ \forall i \in [2,n],都有A_1 >A_i$. 现在需要把这个序 ...
- 后缀数组 POJ 3581 Sequence
题目链接 题意:把n个数字(A1比其他数字都大)的序列分成三段,每段分别反转,问字典序最小的序列. 分析:因为A1比其他数字都大,所以反转后第一段结尾是很大的数,相当是天然的分割线,第一段可以单独考虑 ...
- POJ 3581 Sequence(后缀数组)题解
题意: 已知某字符串\(str\)满足\(str_1 > max\{str_2,str_3 \cdots str_n\}\),现要求把这个字符串分成连续的三组,然后每组都翻转,问字典序最小是什么 ...
- POJ3581 Sequence —— 后缀数组
题目链接:https://vjudge.net/problem/POJ-3581 Sequence Time Limit: 5000MS Memory Limit: 65536K Total Su ...
- POJ 2406 KMP/后缀数组
题目链接:http://poj.org/problem?id=2406 题意:给定一个字符串,求由一个子串循环n次后可得到原串,输出n[即输出字符串的最大循环次数] 思路一:KMP求最小循环机,然后就 ...
- POJ 1743-POJ - 3261~后缀数组关于最长字串问题
POJ 1743 题意: 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1~~88范围内的整数,现在要找一个重复的主题.“主题”是整个音符序列的一个子串,它需 ...
- POJ2406 Power Strings —— KMP or 后缀数组 最小循环节
题目链接:https://vjudge.net/problem/POJ-2406 Power Strings Time Limit: 3000MS Memory Limit: 65536K Tot ...
随机推荐
- Maven常见知识介绍
1)pom详解 2)pom详解 3)测试 4)插件与生命周期 5)maven生命周期 6)范围依赖
- mohout安装
安装完成之后的环境变量的配置如下: JAVA_HOME=/usr/local/jdk1.8.0_144JRE_HOME=/usr/java/jdk1.8.0_144/jreCLASSPATH=.:$J ...
- 你是猴子请来的逗比么!IT跳槽大事件
3月招聘大战早已硝烟四起,互联网职场摇身一变成了跳蚤市场,猎头们告诉跳蚤们,跳不跳不是不问题,往哪儿跳才是重点,跳对了高薪期权都如过眼云烟.不过小编不得不说,劳资最痛恨那些跳槽的人啦!就因为加班 ...
- chm文件帮助功能全解
在winform中点击某个按钮弹出关于这个窗体的功能的具体解释文档方法如下: 第一步,使用chm编译工具修改chm每个文档的url 修改完成后保存确认能否打开, 如果不能就使用这个软件的转换功能把ch ...
- urllib基础-利用网站结构爬取网页-百度搜索
有的时候爬取网页,可以利用网站额结构特点爬取网页 在百度搜索框中输入搜索内容,单击搜索,浏览器会发送一个带有参数的url请求.尝试删除其中的一些参数,只剩下wd这个参数.发现wd是搜索内容.这样程序可 ...
- python基础一 day10(1)
要背的:
- Linux命令权限 用户权限 组权限 文件、目录权限
Linux命令的格式是: 命令+选项+参数 命令是必须存在的,选项和参数可以不必存在,不写的情况是有默认的参数 Linux 一切皆文件 对于文件而言,只需要对文件进行读写就可以实现对文件内容内容的增删 ...
- Python基础篇 -- 部分练习题
实现一个整数加法计算器(两个数相加): 如:content = input("请输入内容:") 用户输入:5+9或5+ 9或5 + 9(含空白),然后进行分割转换最终进行整数的计算 ...
- javase(12)_集合框架_Queue
一.Queue Queye接口体系图 体系分析: Deque实现类:ArrayDeque, LinkedList(数组和链表实现双向队列) BlockingDeque实现类:LinkedBlockin ...
- [OpenJudge] 2727 仙岛寻药
2727:仙岛求药 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶.叛逆但孝顺的李逍遥闯进 ...