gym102392 D. Cycle String?
题意
给定一个长度为 2 n 2n 2n的字符串 s s s, s s s首尾相连形成一个环。
你需要对 s s s进行重新排列,使得 s s s满足: s s s的所有长度为 n n n的连续子串均不相同。
思路
可行的构造方法很多,我大致描述一下我的构造方案,文字描述不太清楚,可以直接看代码。
分情况讨论:
如果所有字符出现的次数均满足 c n t [ i ] ≤ n cnt[i]\le n cnt[i]≤n:
则可以将 s s s中的字符按照字典序(也可以不是字典序,但是相同的字符要挨着)输出,例如: s = a a b c a a b c ⇒ s ′ = a a a a b b c c s=aabcaabc\Rightarrow s'=aaaabbcc s=aabcaabc⇒s′=aaaabbcc。
如果存在字符 k e y key key有 c n t [ k e y ] > n cnt[key]>n cnt[key]>n:
可以注意到,如果有 n + 1 n+1 n+1个相同的字符连在一起,就会出现相同的 n n n长子串,所以要将字符 k e y key key分割成 ( n ) + ( c n t [ k e y ] − n ) (n)+(cnt[key]-n) (n)+(cnt[key]−n)。
-
c n t [ k e y ] = 2 ∗ n cnt[key]=2*n cnt[key]=2∗n,所有字符均相同,无法构造。
-
c n t [ k e y ] = 2 ∗ n − 1 cnt[key]=2*n-1 cnt[key]=2∗n−1,则无论将这个单个的字符放到哪个位子,都不能满足条件,无法构造。
-
c n t [ k e y ] = 2 ∗ n − 2 cnt[key]=2*n-2 cnt[key]=2∗n−2,用这两个字符把最长的字符分隔开, s = a a a a b c ⇒ s ′ = b a a a c a s=aaaabc\Rightarrow s'=baaaca s=aaaabc⇒s′=baaaca。
注意!!
这里会出现一种特殊情况,当 s s s中只有两种字符时,无法构造:
- n < c n t [ k e y ] < 2 ∗ n − 2 n<cnt[key]<2*n-2 n<cnt[key]<2∗n−2,将 k e y key key之外的字符串按照情况一排序,然后将 k e y key key字符串插入进去。
AC的代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, cnt[26];
char s[N];
int main() {
cin >> s + 1;
n = strlen(s + 1) / 2;
for (int i = 1; i <= 2 * n; i++) cnt[s[i] - 'a']++;
// 判断有没有字符个数超过n个
int k = -1;
for (int i = 0; i <= 25; i++)
if (cnt[i] > n) k = i;
if (k == -1) {
cout << "YES\n";
for (int i = 0; i <= 25; i++)
for (int j = 1; j <= cnt[i]; j++) printf("%c", 'a' + i);
return 0;
}
// 记录有多少种不同的字符
int num = 0;
for (int i = 0; i <= 25; i++)
if (cnt[i]) num++;
if (cnt[k] >= 2 * n - 2) {
if (num < 3)
cout << "NO\n";
else {
cout << "YES\n";
for (int i = 0; i <= 25; i++) {
if (i == k) continue;
for (int j = 1; j <= cnt[i]; j++) {
printf("%c", 'a' + i);
while (cnt[k] > n) {
printf("%c", 'a' + k);
cnt[k]--;
}
}
}
while (cnt[k]) {
printf("%c", 'a' + k);
cnt[k]--;
}
}
} else {
cout << "YES\n";
for (int i = 0; i <= 25; i++) {
if (i == k) continue;
for (int j = 1; j <= cnt[i]; j++) {
printf("%c", 'a' + i);
while (cnt[k] > n) {
printf("%c", 'a' + k);
cnt[k]--;
}
}
}
while (cnt[k]) {
printf("%c", 'a' + k);
cnt[k]--;
}
}
return 0;
}