编辑距离算法全解析:优化文本处理的关键技术

本文介绍了使用Python实现编辑距离算法的多种方法,包括动态规划、空间优化的动态规划、递归加记忆化、迭代加记忆化以及基于编辑操作的动态规划。这些方法在自然语言处理、数据库记录匹配和生物信息学中有广泛应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
python源码解读
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

这是力扣72题:编辑距离

题目描述

给定两个单词 word1word2,计算出将 word1 转换成 word2 所使用的最少操作数。

你可以对一个单词进行如下三种操作:

  1. 插入一个字符
  2. 删除一个字符
  3. 替换一个字符
输入格式
  • word1:一个字符串。
  • word2:一个字符串。
输出格式
  • 返回将 word1 转换成 word2 的最小操作数。

示例

示例 1
输入: word1 = "horse", word2 = "ros"
输出: 3
解释: 
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2
输入: word1 = "intention", word2 = "execution"
输出: 5
解释: 
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

方法一:动态规划

解题步骤
  1. 定义状态数组dp[i][j] 表示 word1 的前 i 个字母转换成 word2 的前 j 个字母所使用的最少操作。
  2. 初始化边界:初始化 dp 数组的第一行和第一列,分别表示空字符串到任意长度字符串的转换。
  3. 状态转移方程
    • 如果 word1[i-1] == word2[j-1],则 dp[i][j] = dp[i-1][j-1]
    • 否则,取插入、删除、替换操作的最小值加一,即 dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
  4. 计算最终结果:返回 dp[m][n]
完整的规范代码
def minDistance(word1, word2):
    """
    使用动态规划解决编辑距离问题
    :param word1: str, 第一个单词
    :param word2: str, 第二个单词
    :return: int, 最少操作数
    """
    m, n = len(word1), len(word2)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(1, m + 1):
        dp[i][0] = i
    for j in range(1, n + 1):
        dp[0][j] = j

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if word1[i - 1] == word2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1

    return dp[m][n]

# 示例调用
print(minDistance("horse", "ros"))  # 输出: 3
print(minDistance("intention", "execution"))  # 输出: 5
算法分析
  • 时间复杂度:(O(m * n)),其中 mn 分别是两个字符串的长度。
  • 空间复杂度:(O(m * n)),用于存储 dp 表。

方法二:空间优化的动态规划

解题步骤
  1. 使用滚动数组:使用两行(当前行和前一行)或一行(滚动更新)来减少空间复杂度。
  2. 状态转移:更新 dp 数组时,只依赖于当前行的前一个元素和上一行的元素,因此可以用一维数组滚动更新。
完整的规范代码
def minDistance(word1, word2):
    """
    使用空间优化的动态规划解决编辑距离问题
    :param word1: str, 第一个单词
    :param word2: str, 第二个单词
    :return: int, 最少操作数
    """
    if len(word1) < len(word2):
        word1, word2 = word2, word1
    m, n = len(word1), len(word2)
    previous, current = list(range(n + 1)), [0] * (n + 1)

    for i in range(1, m + 1):
        current[0] = i
        for j in range(1, n + 1):
            if word1[i - 1] == word2[j - 1]:
                current[j] = previous[j - 1]
            else:
                current[j] = min(previous[j - 1], previous[j], current[j - 1]) + 1
        previous, current = current, previous

    return previous[n]

# 示例调用
print(minDistance("horse", "ros"))  # 输出: 3
print(minDistance("intention", "execution"))  # 输出: 5
算法分析
  • 时间复杂度:(O(m * n)),与完整的动态规划相同。
  • 空间复杂度:(O(min(m, n))),只使用两个长度为 n + 1 的数组。

方法三:递归加记忆化

解题步骤
  1. 定义递归函数:定义一个递归函数来计算 word1[0...i]word2[0...j] 的编辑距离。
  2. 记忆化存储:使用一个二维数组来存储已计算的结果,避免重复计算。
  3. 递归计算:基于给定的操作计算最小编辑距离。
完整的规范代码
def minDistance(word1, word2):
    """
    使用递归加记忆化解决编辑距离问题
    :param word1: str, 第一个单词
    :param word2: str, 第二个单词
    :return: int, 最少操作数
    """
    memo = {}

    def dp(i, j):
        if (i, j) in memo:
            return memo[(i, j)]
        if i == 0: return j
        if j == 0: return i
        if word1[i - 1] == word2[j - 1]:
            ans = dp(i - 1, j - 1)
        else:
            ans = min(dp(i - 1, j), dp(i, j - 1), dp(i - 1, j - 1)) + 1
        memo[(i, j)] = ans
        return ans

    return dp(len(word1), len(word2))

# 示例调用
print(minDistance("horse", "ros"))  # 输出: 3
print(minDistance("intention", "execution"))  # 输出: 5
算法分析
  • 时间复杂度:(O(m * n)),递归处理每对索引一次。
  • 空间复杂度:(O(m * n)),用于存储递归调用栈和记忆化结果。

方法四:迭代加记忆化

解题步骤
  1. 初始化:建立一个二维数组用于记忆化存储。
  2. 基本情况填充:填充数组的基本情况(一个字符串为空的情况)。
  3. 迭代计算:使用之前填充的结果迭代计算整个 dp 表。
完整的规范代码
def minDistance(word1, word2):
    """
    使用迭代加记忆化解决编辑距离问题
    :param word1: str, 第一个单词
    :param word2: str, 第二个单词
    :return: int, 最少操作数
    """
    m, n = len(word1), len(word2)
    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 word1[i - 1] == word2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1

    return dp[m][n]

# 示例调用
print(minDistance("horse", "ros"))  # 输出: 3
print(minDistance("intention", "execution"))  # 输出: 5

方法五:基于编辑操作的动态规划

解题步骤
  1. 分析编辑操作:将编辑操作细分为插入、删除、替换,并为每种操作定义独立的逻辑。
  2. 逐步构建解决方案:基于以上操作,构建一个解决方案,逐步填充 dp 表。
完整的规范代码
def minDistance(word1, word2):
    """
    基于编辑操作的动态规划解决编辑距离问题
    :param word1: str, 第一个单词
    :param word2: str, 第二个单词
    :return: int, 最少操作数
    """
    m, n = len(word1), len(word2)
    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 word1[i - 1] == word2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                insert_op = dp[i][j - 1]
                delete_op = dp[i - 1][j]
                replace_op = dp[i - 1][j - 1]
                dp[i][j] = min(insert_op, delete_op, replace_op) + 1

    return dp[m][n]

# 示例调用
print(minDistance("horse", "ros"))  # 输出: 3
print(minDistance("intention", "execution"))  # 输出: 5

不同算法的优劣势对比

特征方法一:动态规划方法二:空间优化DP方法三:递归加记忆化方法四:迭代加记忆化方法五:基于编辑操作DP
时间复杂度(O(m * n))(O(m * n))(O(m * n))(O(m * n))(O(m * n))
空间复杂度(O(m * n))(O(min(m, n)))(O(m * n))(O(m * n))(O(m * n))
优势易于理解和实现空间复杂度较低避免重复计算,提高效率适合大规模数据处理直观反映不同编辑操作
劣势空间占用大代码稍复杂空间占用大空间占用大实现较为复杂

应用示例

自然语言处理:在自然语言处理领域,编辑距离用来衡量两个词语之间的相似度,常用于拼写检查、语音识别系统等领域。

数据库记录匹配:在数据清洗过程中,编辑距离可以帮助识别和合并重复的记录,例如在客户数据库中识别重复的客户名称。

生物信息学:在生物信息学中,编辑距离用于比较基因序列的相似性,对于基因编辑和比较具有重要的应用价值。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据分析螺丝钉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值