华为OD机试_2025 B卷_相对开音节(Python,100分)(附详细解题思路)
题目描述
相对开音节构成的结构为:辅音 + 元音(aeiou)+ 辅音(r除外) + e。
常见的单词有bike、cake等。
给定一个字符串,以空格为分隔符,反转每个单词中的字母,若单词中包含如数字等其他非字母时不进行反转。
反转后计算其中含有相对开音节结构的子串个数(连续的子串中部分字符可以重复)。
输入描述
字符串,以空格分割的多个单词,字符串长度<10000,字母只考虑小写
输出描述
含有相对开音节结构的子串个数,注:个数<10000
用例
输入 | ekam a ekac |
输出 | 2 |
说明 | 反转后为 make a cake 其中make、cake为相对开音节子串,返回2。 |
输入 | !ekam a ekekac |
输出 | 2 |
说明 | 反转后为!ekam a cakeke 因!ekam含非英文字符所以未反转,其中 cake、keke为相对开音节子串,返回2。 |
相对开音节子串统计:反转与模式匹配
核心解题思路
本题要求统计字符串中相对开音节子串的数量,解题关键在于:
- 单词反转条件:仅当单词全为字母时才反转
- 开音节模式匹配:识别"辅音+元音+辅音(非r)+e"的结构
- 子串统计:统计所有符合开音节模式的连续4字符子串
处理流程
- 分割单词:将输入字符串按空格分割
- 条件反转:
- 检查单词是否全为字母
- 是:反转单词
- 否:保持原样
- 开音节匹配:
- 遍历每个处理后的单词
- 检查所有连续的4字符子串
- 验证是否符合开音节结构
- 结果统计:累计所有符合条件的子串数量
完整代码实现
def count_kai_syllables():# 输入处理s = input().strip()words = s.split()# 处理后的单词列表processed_words = []# 1. 条件反转单词for word in words:# 检查是否全为字母if word.isalpha():# 反转单词processed_words.append(word[::-1])else:processed_words.append(word)# 2. 开音节模式匹配count = 0vowels = "aeiou"for word in processed_words:# 跳过长度小于4的单词if len(word) < 4:continue# 遍历所有可能的4字符子串for i in range(len(word) - 3):# 提取连续4个字符substr = word[i:i+4]# 检查开音节模式# 条件1: 首字符是辅音(非元音)if substr[0] in vowels:continue# 条件2: 第二字符是元音if substr[1] not in vowels:continue# 条件3: 第三字符是辅音且非'r'if substr[2] in vowels or substr[2] == 'r':continue# 条件4: 第四字符是'e'if substr[3] != 'e':continue# 所有条件满足,计数增加count += 1# 返回结果return count# 主程序
if __name__ == "__main__":result = count_kai_syllables()print(result)
算法原理解析
1. 条件反转逻辑
if word.isalpha():processed_words.append(word[::-1])
else:processed_words.append(word)
isalpha()
方法检查单词是否全由字母组成- 反转使用切片操作
[::-1]
- 非字母单词保持原样
2. 开音节模式验证
# 条件1: 首字符是辅音(非元音)
if substr[0] in vowels: continue# 条件2: 第二字符是元音
if substr[1] not in vowels: continue# 条件3: 第三字符是辅音且非'r'
if substr[2] in vowels or substr[2] == 'r': continue# 条件4: 第四字符是'e'
if substr[3] != 'e': continue
- 四层条件检查确保完全匹配开音节模式
- 使用
continue
提前终止不满足条件的检查 - 仅当所有条件满足时才计数
3. 子串遍历方式
for i in range(len(word) - 3):substr = word[i:i+4]
- 滑动窗口遍历所有可能的4字符子串
- 窗口大小固定为4,每次滑动1个字符
- 确保处理所有可能的连续子串组合
示例解析
示例1:输入"ekam a ekac"
- 单词分割:[“ekam”, “a”, “ekac”]
- 条件反转:
- “ekam"全字母 → 反转为"make”
- “a"全字母 → 反转为"a”(长度<4,跳过)
- “ekac"全字母 → 反转为"cake”
- 开音节匹配:
- “make”:子串"make" → m(辅音)+a(元音)+k(辅音非r)+e → 匹配
- “cake”:子串"cake" → c(辅音)+a(元音)+k(辅音非r)+e → 匹配
- 结果统计:2
示例2:输入"!ekam a ekekac"
- 单词分割:[“!ekam”, “a”, “ekekac”]
- 条件反转:
- “!ekam"含非字母 → 保持”!ekam"
- “a"全字母 → 反转为"a”(长度<4,跳过)
- “ekekac"全字母 → 反转为"cakeke”
- 开音节匹配:
- “!ekam”:所有子串含非字母或元音开头 → 无匹配
- “cakeke”:
- 子串"cake":c+a+k+e → 匹配
- 子串"akek":a开头 → 不匹配
- 子串"keke":k(辅音)+e(元音)+k(辅音非r)+e → 匹配
- 结果统计:2
边界情况分析
-
短单词处理:
if len(word) < 4:continue
- 长度小于4的单词无法形成开音节子串
- 直接跳过提高效率
-
非字母处理:
- 包含非字母的单词不反转
- 开音节匹配时自动跳过含非字母的子串(条件检查失败)
-
重叠子串:
for i in range(len(word) - 3):
- 滑动窗口确保检查所有可能的子串
- 包括重叠的子串(如"cakeke"中的"cake"和"keke")
总结
算法特点
- 时间复杂度:O(n×m),n为单词数,m为平均单词长度
- 空间复杂度:O(n),存储处理后的单词
- 高效性:滑动窗口+条件短路优化
- 健壮性:正确处理各种边界情况
实际应用
- 自然语言处理:音节模式识别
- 文本分析:单词结构统计
- 语音处理:发音模式检测
- 密码学:模式匹配算法
- 生物信息学:DNA序列模式识别
通过这个解法,初学者可以掌握字符串处理的核心技巧:条件反转、模式匹配和子串统计,为更复杂的文本处理问题奠定基础。