1 条题解
-
0
题目大意
给定一个字符串 (只包含大写字母),可以删除任意字符并重新排列剩余字符,要求组成一个单词。单词由若干个音节拼接而成,每个音节的结构为:
辅音 + 元音 + 辅音(按顺序)。特殊规则:
- 字母
A, E, I, O, U只能作元音。 - 字母
Y可以作元音或辅音。 - 其余字母(除
A, E, I, O, U, Y外)只能作辅音。 - 字符串
"NG"作为一个整体可以当作一个辅音(即两个字母N和G连在一起视为一个辅音单位)。
求能组成的最长单词的长度(即所用字母的总数),若无法组成任何单词则输出 。
解题思路
1. 基本统计
设原始字符串中:
- :普通元音(
A, E, I, O, U)的个数。 - :普通辅音(除
A, E, I, O, U, Y, N, G外的字母)的个数。 - :字母
Y的个数。 - :字母
N的个数。 - :字母
G的个数。
2. 决策变量
由于
Y可以扮演两种角色,N和G可以单独使用或组合成"NG"辅音单位,我们需要枚举:- :使用多少个
"NG"辅音单位()。 - :将多少个
Y用作元音(),则用作辅音的Y个数为 。
3. 可用资源计算
对于一组固定的 :
-
元音总数:
-
辅音“位置”总数(每个位置对应一个辅音,但
"NG"占两个字母却只算一个位置):
包括:- 普通辅音 个(每位置 1 字母)
- 用作辅音的 : 个(每位置 1 字母)
- 剩余的单独
N和G: 个(每位置 1 字母) - 使用的
"NG"单位: 个(每位置 2 字母)
因此辅音位置总数:
$$c = C_0 + (Y - y) + (N + G - 2x) + x = C_0 + Y - y + N + G - x $$ -
可用
"NG"单位数:。
4. 最大音节数
每个音节需要 个元音和 个辅音位置,因此最大可能的音节数(不考虑
$$s_{\max} = \min\left(v,\ \left\lfloor \frac{c}{2} \right\rfloor\right) $$"NG"带来的长度优势)为:实际构造时,只需取出 个元音和 个辅音位置即可。为了最大化总字母数,应尽可能多用
"NG"单位(因为每个"NG"贡献 2 字母,而普通辅音只贡献 1 字母)。在 个辅音位置中,最多能使用 个"NG"单位。5. 单词长度计算
每个音节的基础长度是 (两个单字母辅音 + 一个元音),每将一个普通辅音替换为
"NG"会额外增加 个字母。因此总长度为:其中 取 时能得到最大长度。可以证明,取 一定优于任何更小的 (因为减少音节数会同时减少 项,而 最多线性增长,不可能弥补损失),因此只需计算 对应的长度即可。
6. 算法步骤
- 统计 。
- 初始化答案 。
- 枚举 :
- 枚举 :
- 更新
- 枚举 :
- 输出 。
7. 复杂度分析
枚举 最多 种, 最多 种,总复杂度 。由于 ,,在时限内可行。实际实现时可以剪枝优化,但按题目给定的标程思路已足够。
8. 样例验证
以样例 1
"ICPCJAKARTA"为例:- (A×3, I×1),,,,。
- 唯一组合 :, , , ,输出 9,正确。
其它样例均可通过手动验证。
参考代码(C++)
#include <bits/stdc++.h> using namespace std; int main() { string s; cin >> s; int V0 = 0, C0 = 0, Ycnt = 0, Ncnt = 0, Gcnt = 0; for (char ch : s) { if (ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') V0++; else if (ch == 'Y') Ycnt++; else if (ch == 'N') Ncnt++; else if (ch == 'G') Gcnt++; else C0++; } int ans = 0; for (int x = 0; x <= min(Ncnt, Gcnt); x++) { for (int y = 0; y <= Ycnt; y++) { int v = V0 + y; int c = C0 + (Ycnt - y) + (Ncnt + Gcnt - x); int s = min(v, c / 2); int len = 3 * s + min(x, 2 * s); ans = max(ans, len); } } cout << ans << endl; return 0; } - 字母
- 1
信息
- ID
- 7146
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者