一直以为这个算法实现起来的代码量很高,直到最近刷 《Speech and Language Processing》,用动态规划做起来,简单、优雅。
算法原理
字符串 X,Y 的长度分别是 i, j 求他们的最小编辑距离。
只会有 insertion/deletion/substitution 3 个操作。
所有,有 3 个方法可以从子串推导出他们的最小编辑距离。
在 1966 年 Levenshtein 的论文里,insertion/deletion/substitution 3 个操作的 cost 都是 1。leetcode 上也是这个版本。
Levenshtein 还建议了另外一个版本,insertion/deletion 的 cost 是 1,禁止 substitution。等价于 substitution 的 cost 为 2(一增一减)
伪代码
时间复杂度为 O(mn), 空间复杂度 O(m)。
空间复杂度可以优化到 O(min(m,n)),但没有做。
案例
计算 execution 和 intention 的最小编辑距离,insertion 和 deletion 的 cost 为 1,substitution 的 cost 为 2. 得到的 D 矩阵如下
Python 实现
def minDistance(word1, word2):
if not word1:
return len(word2 or '') or 0
if not word2:
return len(word1 or '') or 0
size1 = len(word1)
size2 = len(word2)
last = 0
tmp = range(size2 + 1)
value = None
for i in range(size1):
tmp[0] = i + 1
last = i
# print word1[i], last, tmp
for j in range(size2):
if word1[i] == word2[j]:
value = last
else:
value = 1 + min(last, tmp[j], tmp[j + 1])
# print(last, tmp[j], tmp[j + 1], value)
last = tmp[j+1]
tmp[j+1] = value
# print tmp
return value
简单的测试代码
assert minDistance(None, None) == 0
assert minDistance(None, '') == 0
assert minDistance('', None) == 0
assert minDistance(None, '1') == 1
assert minDistance('22', None) == 2
assert minDistance('', '') == 0
assert minDistance('h', '') == 1
assert minDistance('', 'r') == 1
assert minDistance('horse', '') == 5
assert minDistance('', 'ros') == 3
assert minDistance('h', 'r') == 1
assert minDistance('horse', 'ros') == 3
leetcode 性能统计
遗留的问题substitution 取 1 和 2 的效果对比