题目描述
小敏和小燕是一对好朋友。
他们正在玩一种神奇的游戏,叫Minecraft。
他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。
他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。
两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块。如果全都一样,那么这两个工艺品就一样漂亮。
题解:
一道最小表示法的模板题。
最小表示法:
有一个首尾相连的字符串,我们需要求出它的最小字典序表示的字符串
首先定义两个指针
i
i
i和
j
j
j,表示从这两个位置开始形成的字符串,然后我们比较它们的字典序,用一个k来计数,从这两个位置开始有多少个字符是相等的,即
s
t
r
[
i
]
=
=
s
t
r
[
j
]
str[i]==str[j]
str[i]==str[j],然后
k
+
1
k+1
k+1,如果在某个位置不相等了,说明:
当
s
t
r
[
i
]
>
s
t
r
[
j
]
str[i] > str[j]
str[i]>str[j],表示
i
i
i开始的字符串比
j
j
j开始的字符串字典序大,又因为
i
i
i和
j
j
j开始的两个位置中有k个字符是相等的,所以我们将i向后移动
k
+
1
k+1
k+1位即可
反之让
j
j
j向后移动
k
+
1
k+1
k+1位
最后返回
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 6e5+50;
inline int read(){
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<<1)+(x<<3)+ch-48,ch=getchar();
return x*f;
}
int a[MAXN],n;
inline int solve(){
int i=1,j=2;
while(i<=n && j<=n){
int k = 0;
while(a[i+k]==a[j+k]) k++;
if(k==n) break;
if(a[i+k]>a[j+k]) i=i+k+1;
else j=j+k+1;
if(i==j) j++;
}
return min(i,j);
}
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=a[i+n]=read();
int pos = solve();
for(int i=pos;i<pos+n;i++) printf("%d ",a[i]); puts("");
return 0;
}