设为首页 加入收藏

TOP

poj 3581 Sequence(一)
2014-11-24 11:02:52 】 浏览:4403
Tags:poj 3581 Sequence

题目大意:求将一个串分成三段再反转后字典序最小。

题目思路:由于题目中说第一个数最大,所以第一切点只要找到最小后缀就可以了,对于剩下的部分,我想到的办法很麻烦,还要求最长公共前缀,分三段比较。网上的方法是将剩余串增倍,因为其实反转后两个串构成一个循环,用加倍的方法可以避免讨论,这样就可以直接用rank比较了。

方法一:

[cpp]
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define M 210000
int max(int a,int b)
{
return a>b a:b;
}
int min(int a,int b)
{
return a }
int rank[M],height[M],sa[M];
int ts[M],tv[M],ta[M],tb[M],r[M],mm[M],dp[20][M];
bool cp(int a,int b)
{
return r[a] }
bool cmp(int *y,int a,int b,int l)
{
return y[a]==y[b]&&y[a+l]==y[b+l];
}
void da(int n)
{
int i,j,*x=ta,*y=tb,m,p;

for(i=0;i sort(y,y+n,cp);
for(i=0;i x[sa[0]]=0;
p=1;
for(i=1;i {
if(r[sa[i]]==r[sa[i-1]]) x[sa[i]]=p-1;
else x[sa[i]]=p++;
}
m=p;
for(j=1,p=1;p {
p=0;
for(i=n-j;i for(i=0;i=j) y[p++]=sa[i]-j;
for(i=0;i for(i=0;i for(i=0;i for(i=1;i for(i=n-1;i>=0;i--) sa[--ts[tv[i]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
for(i=1;i {
if(cmp(y,sa[i-1],sa[i],j)) x[sa[i]]=p-1;
else x[sa[i]]=p++;
}
}
}
void calh(int n)
{
int i,k;
for(i=1;i<=n;i++) rank[sa[i]]=i;
k=0;
for(i=0;i {
int tmp=sa[rank[i]-1];
for(;r[i+k]==r[tmp+k];k++)
;
height[rank[i]]=k;
k --k:0;
}
}
void initrmp(int n)
{
int i,j,tmp;
mm[0]=-1;
for(i=1;i<=n;i++) mm[i]=(i&(i-1)) mm[i-1]:mm[i-1]+1;
for(i=1;i<=n;i++) dp[0][i]=height[i];
for(i=1;i<=mm[n];i++)
{
tmp=1<<(i-1);
for(j=1;j<=n&&j+tmp<=n;j++)
dp[i][j]=min(dp[i-1][j],dp[i-1][j+tmp]);
}
}
int lcp(int a,int b)
{
a=rank[a],b=rank[b];
if(a>b) swap(a,b);
a++;
int l=mm[b-a+1];
b-=(1< return min(dp[l][a],dp[l][b]);
}
int main()
{
int i,n,st1;
scanf("%d",&n);
for(i=n-1;i>=0;i--)
{
scanf("%d",&r[i]);
}
r[n]=-inf;
da(n+1);

calh(n);
initrmp(n);
int mi=inf;
for(i=2;i {
if(rank[i] {
mi=rank[i];
st1=i;
}
}
int rec=1;
for(i=2;i {
if(lcp(rec,i) {
if(rank[i] rec=i;
}
else
{
if(lcp(rec+(st1-i),0) {
if(rank[0] rec=i;
}
else
{
if(rank[i-rec] rec=i;
}
}
}
for(i=st1;i printf("%d\n",r[i]);
for(i=rec;i printf("%d\n",r[i]);
for(i=0;i printf("%d\n",r[i]);
}
方法二:

[cpp]
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define M 410000
int max(int a,int b)
{
return a>b a:b;
}
int min(int a,int b)
{
return a }
int rank[M],height[M],sa[M];
int ts[M],tv[M],ta[M],tb[M],r[M],mm[M],dp[20][M];
bool cp(int a,int b)
{
return r[a] }
bool cmp(int *y,int a,int b,int l)
{
return y[a]==y[b]&&y[a+l]==y[b+l];
}
void da(int n)
{
int i,j,*x=ta,*y=tb,m,p;

for(i=0;i sort(y,y+n,cp);
for(i=0;i x[sa[0]]=0;
p=1;
for(i=1;i {
if(r[sa[i]]==r[sa[i-1]]) x[sa[i]]=p-1;
else x[sa[i]

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++开发指导之使用编译期的契约:.. 下一篇C++复习笔记---类的函数指针和普..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目