返回

动态规划经典题:编辑距离详解,掌握算法精髓

人工智能

动态规划经典教学题:编辑距离详解

前言

大家好,我是算法工程师小明。今天,我们一起来学习动态规划的经典教学题——编辑距离。这道题是算法面试中常考题,掌握它的解题思路和算法实现,对提升算法面试通过率大有裨益。

什么是编辑距离?

编辑距离,又称Levenshtein距离,衡量两个字符串之间的相似度。它表示将一个字符串转换为另一个字符串所需的最小编辑操作数,这些操作包括:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

问题

给定两个字符串 str1str2,计算将 str1 转换为 str2 所需的最小编辑距离。

动态规划解法

我们使用动态规划来解决这个问题。首先,我们创建一张二维表 dp,其中 dp[i][j] 表示将 str1[0:i] 转换为 str2[0:j] 所需的最小编辑距离。

状态转移方程

dp 表的计算方式如下:

dp[i][j] = min(dp[i-1][j] + 1, dp[i][j-1] + 1, dp[i-1][j-1] + (str1[i] != str2[j]))

其中:

  • dp[i-1][j] + 1:从 str1[0:i-1] 转换为 str2[0:j],然后在 str1 末尾插入一个字符。
  • dp[i][j-1] + 1:从 str1[0:i] 转换为 str2[0:j-1],然后在 str2 末尾删除一个字符。
  • dp[i-1][j-1] + (str1[i] != str2[j]):从 str1[0:i-1] 转换为 str2[0:j-1],然后替换第 i 个字符(如果 str1[i]str2[j] 不相等)。

初始化

dp[0][j] = j
dp[i][0] = i

这是因为将空字符串转换为一个非空字符串需要 j 次插入,而将一个非空字符串转换为空字符串需要 i 次删除。

计算

dp[1][1] 开始,按照状态转移方程计算 dp 表中的所有元素。

结果

dp[m][n],其中 mn 分别是 str1str2 的长度,即为将 str1 转换为 str2 所需的最小编辑距离。

代码实现

def edit_distance(str1, str2):
    m, n = len(str1), len(str2)
    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):
            dp[i][j] = min(
                dp[i-1][j] + 1,
                dp[i][j-1] + 1,
                dp[i-1][j-1] + (str1[i-1] != str2[j-1])
            )

    return dp[m][n]

示例

str1 = "abc"
str2 = "abd"
result = edit_distance(str1, str2)
print(result)  # 输出:1

总结

编辑距离是动态规划中的经典问题,它衡量两个字符串之间的相似度,并提供将一个字符串转换为另一个字符串的最小编辑操作数。通过掌握这道题的解题思路和代码实现,我们可以更好地理解动态规划算法,并提升算法面试通过率。