2882: 工藝(最小表示法)
2882: 工藝
Time Limit: 10 Sec Memory Limit: 128 MB
Description
小敏和小燕是一對好朋友。
他們正在玩一種神奇的遊戲,叫Minecraft。
他們現在要做一個由方塊構成的長條工藝品。但是方塊現在是亂的,而且由於機器的要求,他們只能做到把這個工藝品最左邊的方塊放到最右邊。
他們想,在僅這一個操作下,最漂亮的工藝品能多漂亮。
兩個工藝品美觀的比較方法是,從頭開始比較,如果第
個位置上方塊不一樣那麼誰的瑕疵度小,那麼誰就更漂亮,如果一樣那麼繼續比較第
個方塊。如果全都一樣,那麼這兩個工藝品就一樣漂亮。
Input
第一行兩個整數
,代表方塊的數目。
第二行
個整數,每個整數按從左到右的順序輸出方塊瑕疵度的值。
Output
一行 個整數,代表最美觀工藝品從左到右瑕疵度的值。
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%的資料,
對於40%的資料,
對於100%的資料,
解:
這是一個模板題。
最小表示法,但是不能用字尾自動機,字符集太大了。
期望複雜度:
記錄兩個指標 ,列舉比較長度 :
s[i,i+k] = a[j,j+k]
k++
s[i,i+k] < a[j,j+k]
i=i+k
s[i,i+k] > a[j,j+k]
j=j+k
注意比較的時候要取模。
這樣為什麼是對的呢?
拿第二種情況舉例:
i~i+k-1都不可能是最小的,因為用對應的j和它比,都會比它大。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[300005];
int i,j,k,n;
int main()
{
scanf("%d",&n);
for(int w=0;w<n;w++)
scanf("%d",&a[w]);
i=0,j=1,k=0;
while(k<n){
if(a[(i+k)%n]==a[(j+k)%n]) k++;
else if(a[(i+k)%n]>a[(j+k)%n]) k=0,i+=k+1;
else if(a[(i+k)%n]<a[(j+k)%n]) k=0,j+=k+1;
if(i==j) j++;
if(i>j) swap(i,j);
if(j>=n) break;
}
for(int w=0;w<n;w++)
printf("%d ",a[(i+w)%n]);
}