bzoj2882 工艺
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2882
题意:
小敏和小燕是一对好朋友。
他们正在玩一种神奇的游戏,叫Minecraft。
他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。
他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。
两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块。如果全都一样,那么这两个工艺品就一样漂亮。
数据范围
n<=300000
题解:
求一个字符串的最小表示。
把S复制一遍接在后面,对于这个新串建立SAM,
于是从root开始走len次就是那个最小表示。
字符集很大用map。
等学了最小表示法再来UPD一发。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=600005;
struct node
{
int pa,len;
map<int,int> ch;
}tr[2*N+100];
int s[N],n,root=0,last=0,tail=0,tmp;
void add(int c)
{
int nd=++tail; tr[nd].len=tr[last].len+1;
for(tmp=last;tmp&&!tr[tmp].ch[c];tmp=tr[tmp].pa) tr[tmp].ch[c]=nd;
if(!tmp) tr[nd].pa=root;
else
{
int B=tr[tmp].ch[c];
if(tr[B].len==tr[tmp].len+1) tr[nd].pa=B;
else
{
int nB=++tail;
tr[nB]=tr[B]; tr[nB].len=tr[tmp].len+1;
for(;tr[tmp].ch[c]==B;tmp=tr[tmp].pa)
tr[tmp].ch[c]=nB;
tr[nd].pa=nB; tr[B].pa=nB;
}
}
last=nd;
}
void getans()
{
int tmp=root;
map<int,int>::iterator p;
for(int i=1;i<=n;i++)
{
p=tr[tmp].ch.begin();
if(i!=n) printf("%d ",p->first); else printf("%d\n",p->first);
tmp=p->second;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&s[i]);
for(int i=n+1;i<=2*n;i++) s[i]=s[i-n];
root=last=++tail;
for(int i=1;i<=2*n;i++) add(s[i]);
getans();
return 0;
}

本文介绍了一道题目BZOJ2882的解题思路及实现代码,该题要求通过特定操作找到由方块构成的长条工艺品的最漂亮形态。采用字符串最小表示法结合SAM(Suffix Array Manber)算法解决。
689

被折叠的 条评论
为什么被折叠?



