bzoj2882: 工艺
2882: 工艺
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 716 Solved: 324
[Submit][Status][Discuss]
Description
小敏和小燕是一对好朋友。
他们正在玩一种神奇的游戏,叫Minecraft。
他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。
他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。
两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块。如果全都一样,那么这两个工艺品就一样漂亮。
Input
第一行两个整数n,代表方块的数目。
第二行n个整数,每个整数按从左到右的顺序输出方块瑕疵度的值。
Output
一行n个整数,代表最美观工艺品从左到右瑕疵度的值。
Sample Input
10
10 9 8 7 6 5 4 3 2 1
Sample Output
1 10 9 8 7 6 5 4 3 2
HINT
【数据规模与约定】
对于20%的数据,n<=1000
对于40%的数据,n<=10000
对于100%的数据,n<=300000
题解
咳咳我就是贴个代码……嗯最小表示法嘛大家都会的……就是求一个串的字典序最小的循环同构串……如题目那样的定义……
其实我是今天才学的……还是在代码里打个注释吧
program j01; var n,i,pos:longint; s:array[0..600086]of longint; function min(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end; function get:longint; var i,j,k:longint; begin i:=1;j:=2;//i是当前指针(循环同构串的起点),j是和i比较的指针 while(i<=n)and(j<=n) do begin k:=0; while(s[i+k]=s[j+k])and(k<n) do inc(k);//找到第一个不一样的地方 if k=n then exit(i);//比完了n个都没不同就说明i是最小的……不用解释了 if(s[i+k]>s[j+k]) then i:=i+k+1 else j:=j+k+1; //这里就是说啊,因为我们k是一个一个比较过来的,所以说假如有0<=x<=k,(假如s[i+k]>s[j+k])那么如果i+x开始的循环同构串一定比j+x大(因为i+x到i+k的每个字符大小实际上我们已经比较过了),都不可能成为最小的,那么直接把i跳到i+k=1。 if i=j then inc(j); end; exit(min(i,j));//当然也有可能存在i跳过头的情况……这时候答案就是j end; begin readln(n); for i:=1 to n do begin read(s[i]);s[i+n]:=s[i]; end; pos:=get; for i:=0 to n-2 do write(s[i+pos],' '); writeln(s[i+n-1]); end.