題意:給定長度為n
nn的序列,求字典序最小的長度為n
nn且與原序列迴圈同構的序列
思路:利用最小表示法(也有字尾自動機以及字尾陣列的解法)
暴力的比較所有的n
nn個迴圈同構的串
純暴力會被卡到o(n
2)
o(n^2)
o(n2
),因此需要加點優化,**如下
#include
"bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)namespace std;
typedef
long
long ll;
typedef pair<
int,
int> pr;
inline
intread()
const
int maxn =
3e5+10;
const
int mod =
1e9+7;
const
double eps =
1e-9
;int a[maxn]
;int
main()
}int start=
min(i,j)
;//由於上面退出迴圈可以分為兩種情況,(i>=n||j>=n)或(k==n)。若k等於n,則i,j隨便輸出乙個,表示原串所有位置都相同;若是另外的情況,肯定輸出i和j中較小的那個
for(
int i=
0; i++i)
printf
("%d%c"
, a[
(start+i)
%n],
" \n"
[i==n-1]
);}
補充乙個最大表示法,相對上面只有一點點修改
#include
"bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)namespace std;
typedef
long
long ll;
typedef pair<
int,
int> pr;
inline
intread()
const
int maxn =
3e5+10;
const
int mod =
1e9+7;
const
double eps =
1e-9
;int a[maxn]
;int
main()
}int start=
min(i,j)
;//由於上面退出迴圈可以分為兩種情況,(i>=n||j>=n)或(k==n)。若k等於n,則i,j隨便輸出乙個,表示原串所有位置都相同;若是另外的情況,肯定輸出i和j中較小的那個
for(
int i=
0; i++i)
printf
("%d%c"
, a[
(start+i)
%n],
" \n"
[i==n-1]
);}
建字尾自動機時用map存邊
由於map已經按照第一關鍵字排序了,因此只需貪心的跑長度為t的串即可(用map.begin()表示字典序最小的邊)
最小表示法 工藝
description 小敏和小燕是一對好朋友。他們正在玩一種神奇的遊戲,叫minecraft。他們現在要做乙個由方塊構成的長條工藝品。但是方塊現在是亂的,而且由於機器的要求,他們只能做到把這個工藝品最左邊的方塊放到最右邊。他們想,在僅這乙個操作下,最漂亮的工藝品能多漂亮。兩個工藝品美觀的比較方法是...
2882 工藝(最小表示法)
time limit 10 sec memory limit 128 mb 小敏和小燕是一對好朋友。他們正在玩一種神奇的遊戲,叫minecraft。他們現在要做乙個由方塊構成的長條工藝品。但是方塊現在是亂的,而且由於機器的要求,他們只能做到把這個工藝品最左邊的方塊放到最右邊。他們想,在僅這乙個操作下...
bzoj2882 工藝 最小表示法
小敏和小燕是一對好朋友。他們正在玩一種神奇的遊戲,叫minecraft。他們現在要做乙個由方塊構成的長條工藝品。但是方塊現在是亂的,而且由於機器的要求,他們只能做到把這個工藝品最左邊的方塊放到最右邊。他們想,在僅這乙個操作下,最漂亮的工藝品能多漂亮。兩個工藝品美觀的比較方法是,從頭開始比較,如果第i...