编辑距离(Edit Distance),也称为Levenshtein距离,是衡量两个字符串之间相似度的一个指标。它表示将一个字符串转换为另一个字符串所需的最小操作次数,操作包括插入、删除和替换字符。
动态规划实现
编辑距离的经典解决方案是使用动态规划。这个方法通过构建一个二维表格来存储中间结果,从而避免重复计算。
算法步骤
-
初始化表格:
- 创建一个二维表格
dp
,其中dp[i][j]
表示将字符串s1[0:i]
转换为s2[0:j]
所需的最小编辑距离。 - 表格的大小是
(m+1) x (n+1)
,其中m
和n
分别是s1
和s2
的长度。
- 创建一个二维表格
-
填充表格:
- 通过比较每个字符并使用递推关系来填充表格。
-
返回结果:
dp[m][n]
将包含将s1
转换为s2
的最小编辑距离。
示例代码
def compute_edit_distance(s1, s2):
m, n = len(s1), len(s2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
# 初始化边界条件
for i in range(m + 1):
dp[i][0] = i
for j in range(n + 1):
dp[0][j] = j
# 填充表格
for i in range(1, m + 1):
for j in range(1, n + 1):
if s1[i - 1] == s2[j - 1]:
cost = 0
else:
cost = 1
dp[i][j] = min(dp[i - 1][j] + 1, # 删除
dp[i][j - 1] + 1, # 插入
dp[i - 1][j - 1] + cost) # 替换
return dp[m][n]
# 使用示例
s1 = "kitten"
s2 = "sitting"
print(compute_edit_distance(s1, s2)) # 输出: 3
解释
dp[i][j]
表示将s1[0:i]
转换为s2[0:j]
的最小编辑距离。- 边界条件
dp[i][0]
和dp[0][j]
分别表示将一个字符串转换为空字符串的距离,即i
或j
。 - 对于每个字符对比,
dp[i][j]
的值取决于三种操作:删除、插入和替换,选择其中最小的一个。
复杂度
- 时间复杂度:
O(m * n)
,其中m
和n
分别是s1
和s2
的长度。 - 空间复杂度:
O(m * n)
,需要一个(m+1) x (n+1)
的表格来存储中间结果。
优化
- 空间优化:可以使用两个一维数组来代替二维表格,将空间复杂度从
O(m * n)
减少到O(n)
。
def compute_edit_distance_optimized(s1, s2):
m, n = len(s1), len(s2)
prev = list(range(n + 1))
curr = [0] * (n + 1)
for i in range(1, m + 1):
curr[0] = i
for j in range(1, n + 1):
if s1[i - 1] == s2[j - 1]:
cost = 0
else:
cost = 1
curr[j] = min(prev[j] + 1, # 删除
curr[j - 1] + 1, # 插入
prev[j - 1] + cost) # 替换
prev, curr = curr, prev
return prev[n]
# 使用示例
s1 = "kitten"
s2 = "sitting"
print(compute_edit_distance_optimized(s1, s2)) # 输出: 3
这种优化通过减少不必要的空间开销,使得算法在空间方面更加高效。