给定一个长度为 n n n 的只有小写字母的字符串 s s s ,随意排列这个字符串,使得字符串正着和反着的最大字典序最小。
我们保证首尾字符尽可能相等,且字符尽可能小。
统计每个字符的出现次数。
记录最小字符 a a a 出现了 c a ca ca 次,大于最小字符 a a a 的字符 b b b 出现了 c b cb cb 次,大于 b b b 的字符 c c c 出现了 c c cc cc 次。
#include
using namespace std;
const int N = 100010;
char s[N];
char ans[N];
int cnt[26];
int n;
void op(int& x, int& y, int i, int j) {
ans[x] = i + 'a';
ans[y] = j + 'a';
cnt[i] -= 1;
cnt[j] -= 1;
x += 1;
y -= 1;
}
void solve() {
memset(cnt, 0, sizeof cnt);
scanf("%s", s + 1);
n = strlen(s + 1);
if (n == 1) {
puts(s + 1);
return ;
}
for (int i = 1; i <= n; ++i) {
cnt[s[i] - 'a'] += 1;
}
ans[n + 1] = 0;
int i = 1, j = n;
while (i < j) {
int id[3] = {-1, -1, -1};
for (int c = 0; c < 26; ++c) {
if (cnt[c] > 0) {
if (id[0] == -1) id[0] = c;
else if (id[1] == -1) id[1] = c;
else if (id[2] == -1) id[2] = c;
else break;
}
}
if (id[0] != -1 && cnt[id[0]] >= 2) {
op(i, j, id[0], id[0]);
continue ;
}
if (id[0] != -1 && id[1] != -1 && cnt[id[0]] == 1 && cnt[id[1]] == 1) {
op(i, j, id[0], id[1]);
break;
}
if (id[2] == -1 && cnt[id[1]] >= 2) {
op(i, j, id[1], id[1]);
continue ;
} else {
op(i, j, id[0], id[1]);
break;
}
}
for (int k = i, c = 25; k <= j; ++k) {
while (c > 0 && cnt[c] == 0) c -= 1;
ans[k] = c + 'a';
cnt[c] -= 1;
}
reverse(ans + 1, ans + n + 1);
printf("%s\n", ans + 1);
}
int main()
{
int T = 1;
scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}