您的位置:首页 > 产品设计 > UI/UE

POJ 3581 Sequence(后缀数组)

2017-09-08 14:53 246 查看
题意:

N个数字组成的序列A1,A2,A3...An。其中,A1最大,现在要把整个序列分成三段,并将三段反转,求能得到的字典序最小的序列是什么?要求分得的每段都不为空。

第一段分割比较简单,反转利用后缀数组即可;剩余的二三段不是独立的,不能光比较前半部分的字典序取其中最小者,我们可以反转二三段并重复2次,再计算其后缀数组,且sa[0]的开始位置应在序列的前半部分,这样,二三段就是按整体考虑了。

代码:(后缀数组

//输入
int N,A[max_n];

int rev[max_n*2],sa[max_n*2];

void solve()
{
//将A反转,并计算其后缀数组
reverse_copy(A,A+N,rev);
creat_sa(rev,N,sa);

//确定第一段的分割位置
int p1;
for(int i=0;i<N;i++)
{
p1=N-sa[i];
if(p1>=1&&N-p1>=2)
break;
}

//将p1之后的字符串反转并重复2次,再计算其后缀数组
int m=N-p1;
reverse_copy(A+p1,A+N,rev);
reverse_copy(A+p1,A+N,rev+m);
creat_sa(rev,m*2,sa);

//确定后两段的划分位置
int p2;
for(int i=0;i<=2*m;i++)
{
p2=p1+m-sa[i];
if(p2-p1>=1&&N-p2>=1) break;
}

reverse(A,A+p1);
reverse(A+p1,A+p2);
reverse(A+p2,A+N);
for(int i=0;i<N;i++)
printf("%d\n",A[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: