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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 编辑距离算法全解析:优化文本处理的关键技术

作者介绍: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
  1. 计算最终结果:返回 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))
优势 易于理解和实现 空间复杂度较低 避免重复计算,提高效率 适合大规模数据处理 直观反映不同编辑操作
劣势 空间占用大 代码稍复杂 空间占用大 空间占用大 实现较为复杂

应用示例

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

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

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

欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
4天前
|
XML 存储 API
RAG效果优化:高质量文档解析详解
本文介绍了如何通过高质量的文档解析提升RAG系统整体的效果。
137 4
|
3天前
|
机器学习/深度学习 算法 TensorFlow
【深度学习】深度学习语音识别算法的详细解析
深度学习语音识别算法是一种基于人工神经网络的语音识别技术,其核心在于利用深度神经网络(Deep Neural Network,DNN)自动从语音信号中学习有意义的特征,并生成高效的语音识别模型。以下是对深度学习语音识别算法的详细解析
13 5
|
1天前
|
机器学习/深度学习 自然语言处理 负载均衡
揭秘混合专家(MoE)模型的神秘面纱:算法、系统和应用三大视角全面解析,带你领略深度学习领域的前沿技术!
【8月更文挑战第19天】在深度学习领域,混合专家(Mixture of Experts, MoE)模型通过整合多个小型专家网络的输出以实现高性能。从算法视角,MoE利用门控网络分配输入至专家网络,并通过组合机制集成输出。系统视角下,MoE需考虑并行化、通信开销及负载均衡等优化策略。在应用层面,MoE已成功应用于Google的BERT模型、Facebook的推荐系统及Microsoft的语音识别系统等多个场景。这是一种强有力的工具,能够解决复杂问题并提升效率。
|
2天前
|
传感器 机器学习/深度学习 人工智能
人工智能中的Agent技术解析
【8月更文挑战第18天】总之,Agent作为人工智能领域的重要分支,将在未来发挥更加重要的作用。随着技术的不断进步和应用场景的不断拓展,Agent技术将为我们带来更加智能、便捷和高效的生活体验。
|
1天前
|
算法
基于GA-PSO遗传粒子群混合优化算法的CVRP问题求解matlab仿真
本文介绍了一种基于GA-PSO混合优化算法求解带容量限制的车辆路径问题(CVRP)的方法。在MATLAB2022a环境下运行,通过遗传算法的全局搜索与粒子群算法的局部优化能力互补,高效寻找最优解。程序采用自然数编码策略,通过选择、交叉、变异操作及粒子速度和位置更新,不断迭代直至满足终止条件,旨在最小化总行驶距离的同时满足客户需求和车辆载重限制。
|
2天前
|
算法 语音技术
支付宝商业化广告算法问题之在ODL模型优化过程中,采取什么策略来提高模型的泛化能力呢
支付宝商业化广告算法问题之在ODL模型优化过程中,采取什么策略来提高模型的泛化能力呢
|
1天前
|
机器学习/深度学习 数据采集 算法
2.6 手写数字识别之优化算法
这篇文章探讨了在手写数字识别任务中,如何通过优化算法来找到使损失函数达到最小的参数取值。文章首先讨论了学习率对模型训练的影响,然后介绍了四种主流的优化算法:SGD、Momentum、AdaGrad和Adam,并说明了每种算法的特点和适用场景。此外,文章还强调了模型参数初始化的重要性,并介绍了几种常用的参数初始化方法,最后指出在实际应用中,使用预训练模型可以加速网络训练并提高精度。
5 0
|
2天前
|
SQL 数据库 数据库管理
SQL查询是否都需要解析:深入解析SQL执行流程与优化技巧
在数据库管理系统中,SQL(Structured Query Language)查询是用户与数据库交互的主要方式
|
3天前
|
编译器 Android开发 开发者
Android经典实战之Kotlin 2.0 迁移指南:全方位优化与新特性解析
本文首发于公众号“AntDream”。Kotlin 2.0 已经到来,带来了 K2 编译器、多平台项目支持、智能转换等重大改进。本文提供全面迁移指南,涵盖编译器升级、多平台配置、Jetpack Compose 整合、性能优化等多个方面,帮助开发者顺利过渡到 Kotlin 2.0,开启高效开发新时代。
8 0
|
4天前
|
存储 SQL 关系型数据库
探索MySQL的执行奥秘:从查询执行到数据存储与优化的深入解析
探索MySQL的执行奥秘:从查询执行到数据存储与优化的深入解析

推荐镜像

更多