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 ...
随机推荐
- Windwos下安装和使用MongoDB
1)下载安装包下载路径:https://www.mongodb.com/download-center#community包名称:mongodb-win32-x86_64-3.4.10-signed. ...
- Entity Framework插入数据报错:Validation failed for one or more entities
www.111cn.net 编辑:lanve 来源:转载 今天在处理Entity Framework插入数据库时,报错: Validation failed for one or more entit ...
- ucosii(2.89)mutex 应用要点
mutex 的创建在于共享资源打交道是可以可以保证满足互斥条件:1,必须保证继承优先级要高于可能与相应共享资源打交道的任务中优先级最高的优先级.2,不要将占有Mutex的任务挂起,也不要让占有mute ...
- 获取显示设备的名称及PNPDeviceID
实现效果: 知识运用: ManagementObjectSearcher类和ManagementObject类 实现代码: private void button1_Click(object send ...
- Open Cascade:拓扑类型(Topo_DS)之间类型转换
TopoDS_Edge aEdge = TopoDS::Edge(myAISShape->Shape()); TopoDS_Wire S1_wire = static_cast(S1); // ...
- 新版raspbian系统的固定IP配置和启用root账户的ssh登录功能的方法
1. 2016新版raspbian系统的固定IP配置: 自2016年2月份新版raspbian系统发布以后,树莓派的固定IP配置方法就与之前不一样了. 之前在raspbian系统中编辑/etc/net ...
- 来自-小坦克:Fiddler教程
Fiddler 教程 阅读目录 Fiddler的基本介绍 Fiddler的工作原理 同类的其它工具 Fiddler如何捕获Firefox的会话 Fiddler如何捕获HTTPS会话 Fiddler的基 ...
- PHP的PDF扩展库TCPDF将中文字体设置为内嵌字体的方法
1. 下载要设置的字体,如名为simfang.ttf,放在./vendor/tecnickcom/tcpdf/tools目录中 2.在tools目录中按住shift,点击鼠标右键,点击“在此处打开命令 ...
- word转HTML在layuiadmin中锚点调转问题
前言: 在以前我们讲过把word转成HTML移植入自己的web项目使用:Word转html并移植到web项目 正文: 发现如果在layuiadmin框架中,页面里锚点跳转时会不正常(会跳转到新页面): ...
- 高度自适应的bug
今天在整理之前IFEde作业,发现有个简历的效果好像没实现.于是想把样式改成作业要求的那样. 作业要求是这样的: 右边栏昨晚高度是839px,我想把左边栏做成高度自适应的.但是没成功.现在我把这个问题 ...