題目
尋找字串 s 的某個排列 t,使得 s 經過相鄰字母交換變成 t 時交換次數最大。
解法
考慮只有兩種字母的情況:
$$s=\texttt{yyyxyyy}$$,x 移到最後或最前即可。
$$s=\texttt{yyxyyxyy}$$,沒必要把兩個 x 移到中間,因為之後可以把他們往左(或右)移動,貢獻值不會更差,必有一個在最左或最右。
假設左邊長度較大,不管中間長度為何,一定一起移到左邊,反之亦然。
$$s=\texttt{yyxyxyxyy}$$ 也可套用同樣概念,相同字母一定在一起。
在多種字母情況,對字母 x 來說,其他字母都是 “別人”,x 一起到最左或右。
對每種字母使用相同概念,雖然不知道他們的順序,但相同字母一定擠在一起。
題目中字串只有四種字母,只要 $$O(4!n)$$ 枚舉他們的排列然後計算最大貢獻就好。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
void solve() {
string s, t = "ANOT", result;
cin >> s;
ll dict[4], max_swap = -1, n_swap;
do {
fill_n(dict, 4, 0);
n_swap = 0;
for(char c : s) {
n_swap += accumulate(dict + t.find(c) + 1, dict + 4, 0ll);
dict[t.find(c)]++;
}
if(n_swap > max_swap) {
max_swap = n_swap;
result = t;
}
} while(next_permutation(all(t)));
fill_n(dict, 4, 0);
for(char c : s) {
dict[result.find(c)]++;
}
for(int i = 0; i < 4; i++) {
cout << string(dict[i], result[i]);
}
cout << '\n';
}
|
參考資料
https://blog.csdn.net/xin_jun/article/details/117393947
https://blog.csdn.net/qq_51945248/article/details/117567898
https://zh.xloypaypa.pub/codeforces-round-723-kill-anton-ti-jie-java-c/
Author
93wilsonlu
LastMod
2021-09-03
License
原創文章,如需轉載請註明文章作者和出處。謝謝!