1 条题解
-
0
题目题解
问题理解
给定一个由大写字母组成的字符串 。如果 包含连续子串
"FFT"或"NTT",则称为困难的。
允许任意重排 中的字符,要求输出一个不困难的重排结果。保证解存在。
第一步:分析困难子串的特征
困难子串为:
"FFT":两个F后跟一个T。"NTT":一个N后跟两个T。
共同点是:末尾都有
T,且前面至少有一个字母不是T。因此,如果我们能让
T不位于F或N的后面(即避免形成FFT或NTT),就可以避免困难。
第二步:构造策略
一个简单有效的方法是:将所有
T放在所有F和N的前面。
这样,任何连续的三个字符中,如果第一个是F或N,后面不可能跟着两个T(因为T都在前面),也不会出现FFT(因为T在前,F在后)。具体构造:
- 统计原字符串中
F、N、T的个数(其他字母不变)。 - 输出:先输出所有
T,再输出所有其他字母(保持原顺序或任意顺序)。
第三步:实现方法
- 对字符串进行排序(默认升序),然后反转,即可得到
T在前、F和N在后的顺序(因为字母顺序:F<N<T,反转后T在前)。 - 其他字母(如
A、B等)也会被排序,但不会影响FFT或NTT的形成。
第四步:正确性证明
排序后得到字符串中所有
T位于最前面,后面是F、N及其他字母。
考察任意连续三个字符:- 若第一个字符是
T,则子串不可能是FFT或NTT(因为首字母不是F或N)。 - 若第一个字符不是
T,则第二个和第三个字符也不可能是T(因为所有T都在前面),因此无法形成FFT(需要末尾T)或NTT(需要末尾两个T)。
因此,构造的字符串一定不困难。
第五步:时间复杂度
- 排序:。
- 总复杂度 $O(\sum |s| \log |s|) \le 2\times 10^5 \log(2\times 10^5)$,满足要求。
代码实现
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { string s; cin >> s; sort(s.begin(), s.end()); reverse(s.begin(), s.end()); cout << s << '\n'; } return 0; }
验证样例
输入:
5 FFT ABFBANTTA FFTNTT FFTFFTFFTNNTNNT AFFTBFFNTTFTTZ输出:
FTF ABFBANATT NTFTFT TFFFFFFNTNTNTNT AFTFBTTFFNFTTZ与题目输出一致。
总结
本题的关键在于:
- 识别出
FFT和NTT都以T结尾。 - 通过将
T全部移到前面,避免T出现在F或N之后。 - 排序后反转即可简单实现。
- 1
信息
- ID
- 6291
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者