时间限制:1秒
空间限制:128M
小码哥最近在研究字符串,如果一个字符串可以被划分为同时满足以下条件的若干个连续的字串,他就称该串为“多重回文串”:
1.每个字符都被划分进恰好一个子串中
2.每个子串都是长度不小于 22 的回文串
现在给出一个字符串 ss,请问能否通过对 ss 中的字符重新排列,使其成为一个“多重回文串”?
输入一行,一个字符串 s s s,满足 ∣ s ∣ ∈ [ 1 , 2 × 1 0 5 ] |s|\in[1,2\times 10^5] ∣s∣∈[1,2×105],保证所有字符均为小写字母。
无
输出一行,YES 或 NO。
aeoooamlml
YES
样例中的字符串可以重新排列为 aoooa mem ll,满足“多重回文串”的定义。
“子串”应该是连续的,并且顺序也不能改变。
这道题字母就完全重组了,只要求每个字母恰好使用一次。
既然题目不要求顺序,那么就好说了,直接所有的字母拿出来,想怎么用就怎么用。
如果要组成回文串,那么前后必须对称。
相同的字母好处理,直接自己就能前后对称。
但是“落单”的字母就需要被“相同”的字母前后夹着(因为题目要求回文串的长度至少为 2 2 2)
因此,问题就转化为了:是否有足够的“相同字母对”,能把“落单的字母”夹在中间。
只需要遍历一遍字符串,统计每个字母出现的次数。
之后遍历 26 26 26个字母,把能成对的全部成对,落单的单着。
然后比较“成对”的对数和“落单”的单数哪个大 就可以了。
/*
* @Author: LetMeFly
* @Date: 2022-08-21 13:11:13
* @LastEditors: LetMeFly
* @LastEditTime: 2022-08-21 13:42:28
*/
#include
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int bin[26] = {0};
int main() {
string s;
cin >> s;
for (char& c : s) { // 遍历字符串统计每个字母出现的次数
bin[c - 'a']++;
}
int cntOdd = 0, cntEven = 0;
for (int i = 0; i < 26; i++) { // 遍历26个字母,统计“成对”、“落单”的字母(对)的个数
if (bin[i]) {
if (bin[i] % 2) { // 这个字母总共出现了奇数次,有一个落单的前提下其他的字母都能成对
bin[i]--;
cntOdd++;
}
cntEven += bin[i] / 2; // 两个字母是一对
}
}
puts(cntEven >= cntOdd ? "YES" : "NO"); // 成对的夹着落单的
return 0;
}
虽然代码可以复制,但最好还是自己理解后再敲哦
原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/126459839