带元音特殊权重的Levenshtein距离函数错误排查求助
分析你的Levenshtein距离函数问题
你的代码主要有三个核心问题,导致计算结果不符合预期:
1. 初始距离数组未区分元音的删除成本
原代码里用distances = range(len(word1) + 1)生成整数数组,但这个数组的每个元素代表把word1前i个字符删除为空字符串的总成本。因为元音的删除成本是0.5而非1,你不能直接用整数来初始化——比如'aaax'的前3个a是元音,删除每个的成本都是0.5,所以初始数组应该是[0, 0.5, 1.0, 1.5, 2.5],而不是[0,1,2,3,4]。
2. 新行的初始化逻辑错误
原代码中distances_ = [it2 + 0.5]或[it2 + 1]是完全错误的。这个位置的元素代表把空字符串插入成word2前it2+1个字符的总成本,需要逐个累加每个字符的插入成本,而不是用it2乘以固定值。比如当word2是'x'时,插入成本是1,初始化值碰巧正确,但如果是多个元音就会出错——比如word2是'aaa',it2=2时正确成本是0.5*3=1.5,而不是2+0.5=2.5。
3. 内层循环的条件分支逻辑混乱
你用了多个独立的if语句,导致distances_被重复追加元素,完全偏离了动态规划的状态转移逻辑。正确的做法是对每个位置计算三种操作(替换、删除、插入)的成本,然后取最小值。
修正后的代码
这里给出符合需求的优化版代码,用一维数组优化空间,同时明确区分各种操作的成本:
def get_char_cost(char): # 返回字符的插入/删除成本,元音0.5,其他1.0(忽略大小写) return 0.5 if char.lower() in {'a', 'e', 'i', 'o', 'u'} else 1.0 def levenshtein_dist(word1, word2): m, n = len(word1), len(word2) # 初始化dp数组:dp[i]表示word1前i个字符转为空的成本(删除操作) dp = [0.0] * (m + 1) for i in range(1, m + 1): dp[i] = dp[i-1] + get_char_cost(word1[i-1]) for j in range(1, n + 1): # 保存上一行的首个元素,避免被覆盖 prev_row_first = dp[0] # 更新当前行首个元素:空转为word2前j个字符的成本(插入操作) dp[0] += get_char_cost(word2[j-1]) for i in range(1, m + 1): # 保存当前dp[i],作为下一轮的上一行值 current_dp = dp[i] # 计算三种操作的成本: # 替换:字符相同则成本0,否则1.0 replace_cost = 0.0 if word1[i-1] == word2[j-1] else 1.0 option_replace = prev_row_first + replace_cost # 删除:删除word1的第i个字符,成本为该字符的删除成本 option_delete = dp[i-1] + get_char_cost(word1[i-1]) # 插入:插入word2的第j个字符,成本为该字符的插入成本 option_insert = dp[i] + get_char_cost(word2[j-1]) # 取最小成本作为当前dp值 dp[i] = min(option_replace, option_delete, option_insert) # 更新prev_row_first为上一行的当前值 prev_row_first = current_dp return dp[m]
测试验证
运行levenshtein_dist('aaax', 'x')会返回1.5,完全符合你的预期。这个结果的逻辑是:删除'aaax'中的三个a(每个成本0.5,总计1.5),最后一个x与目标字符串的x匹配,无需额外成本。
内容的提问来源于stack exchange,提问作者LDR
相关产品推荐
相关产品推荐

