bzoj2882: 工艺

2882: 工艺

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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=1if 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.

 

posted @ 2017-03-06 17:27  OldJang  阅读(250)  评论(0编辑  收藏  举报