通过率 0% · 提交 0 · 通过 0
语音识别评测需要对比参考序列与识别序列:一次编辑指插入、删除或替换一个 token,代价均为 1。编辑距离是把识别序列变成参考序列所需的最少编辑次数。CER 定义为 编辑距离 / 参考序列长度,按四舍五入保留 4 位小数输出。特别地,当参考序列为空时,规定 CER 的数值等于编辑距离本身(仍按 4 位小数格式输出)。
这类题属于算法机考高频题型中「华为 AI 岗 / 编辑距离」方向的高频题型,通常考察对「华为 AI 岗 / 编辑距离」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行输入两个整数 n m,分别是参考序列与识别序列的长度。第二行输入 n 个 token;第三行输入 m 个 token。长度为 0 时对应行为空行。token 由小写字母和数字组成,长度不超过 10。
第一行输出编辑距离。第二行输出 CER,四舍五入保留 4 位小数。
示例 1
输入示例
5 5 a b c d e a x c e f
输出示例
3 0.6000
混合替换/删除/插入
示例 2
输入示例
3 0 w1 w2 w3
输出示例
3 1.0000
识别结果为空
时间限制 3000 ms · 内存限制 256 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
这些是真正决定能不能 AC、但通用题解里常被略过的点。
本题把识别序列变成参考序列,允许插入、删除或替换一个 token,每次操作的代价都是 1。先求最少编辑次数 d,再按参考序列长度 n 计算 CER。这里的计算单位是输入中的 token,而不是 token 内的单个字符。
令 dp[i][j] 表示把识别序列前 j 个 token 变成参考序列前 i 个 token 的最少编辑次数。行对应参考序列,列对应识别序列。
因此,上方格子对应插入,左方格子对应删除;操作名称由这里的转换方向决定,不要只按表格位置记忆。
初始化也按相同含义处理:dp[i][0] = i,因为空识别序列需要插入 i 个 token;dp[0][j] = j,因为要删除识别序列的全部 j 个 token。最终距离是 dp[n][m]。
参考序列为 a b,识别序列为 a。第二个参考 token b 没有对应项,需要插入一次,距离为 1。交换两序列后,则需要删除一次,距离仍为 1,但操作方向不同。仅比较最终距离相同,不能据此判断插入和删除的解释是否正确。
计算当前行 cur 时,只读取上一行的 prev[j-1]、prev[j] 和当前行左侧的 cur[j-1]。保留这两行即可,不必存储整个二维表。每轮先设置 cur[0] = i,再从左到右计算,最后交换两行。
时间复杂度为 O(n·m),滚动数组的额外空间为 O(m)。n、m 均不超过 2000,最多计算 400 万个状态;总内存还包括输入序列。实际运行时间取决于实现与判题环境。
参考序列非空时,CER = d/n。题目要求保留四位小数,并采用通常的四舍五入规则。对非负整数 d 和正整数 n,可以先计算万分之一单位:
q = (20000*d + n) // (2*n)
再把 q//10000 作为整数部分,把 q%10000 补足四位作为小数部分。例如 d=1、n=32,CER=0.03125,应输出 0.0313。Python 的 round 使用中点取偶规则,不能直接用它替代本题的四舍五入;这个例子本身可以精确表示为二进制数,差异不只是浮点表示误差。
参考序列为空时,题目另有约定:CER 的数值等于编辑距离 d,不执行除法。例如 n=0、m=2 时,输出距离 2 和 CER 2.0000。
长度为 0 的序列对应空行。可以把完整输入按空白切成 token 流:先读 n、m,再依次取 n 个参考 token 和 m 个识别 token。按行读取同样可行,但必须保留空序列的位置,不能把后面的行误当成前一个序列。
输出两行:第一行是编辑距离;第二行是四位小数的 CER。参考实现先算距离,再进行整数四舍五入与字符串补零。
1. 参考 a b、识别 a b:距离 0,CER 0.0000。 2. 参考 a b、识别 a:距离 1,CER 0.5000;检查插入方向。 3. 参考 a、识别 a b:距离 1,CER 1.0000;检查删除方向。 4. 参考有 3 个 token、识别为空:距离 3,CER 1.0000。 5. 参考为空、识别有 2 个 token:距离 2,CER 2.0000。 6. 两序列均为空:距离 0,CER 0.0000。 7. 参考长 32,识别只替换其中一个 token:距离 1,CER 0.0313。
这些例子分别检查匹配、编辑方向、空序列与舍入。再加入重复 token 和混合编辑的输入,核对三种转移是否都被考虑。
# 编辑距离:dp[i][j]=识别前 j 个变参考前 i 个的最少编辑,三方向转移滚动一行
# CER 四舍五入用整数式 (20000*d+n)//(2*n),三语言逐位一致
# 读入按 token 总数切,规避空行陷阱
import sys
def solve() -> None:
data = sys.stdin.buffer.read().split()
if not data:
return
n = int(data[0])
m = int(data[1])
ref = data[2:2 + n]
hyp = data[2 + n:2 + n + m]
prev = list(range(m + 1))
for i in range(1, n + 1):
a = ref[i - 1]
cost = [0 if a == h else 1 for h in hyp]
cur = [i] + [0] * m
c = i
pj1 = prev[0]
for j in range(1, m + 1):
pj = prev[j]
x = pj1 + cost[j - 1]
y = pj + 1
if y < x:
x = y
z = c + 1
if z < x:
x = z
cur[j] = x
c = x
pj1 = pj
prev = cur
d = prev[m]
if n > 0:
r = (20000 * d + n) // (2 * n)
else:
r = d * 10000
print(d)
print(f"{r // 10000}.{r % 10000:04d}")
if __name__ == "__main__":
solve()
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。