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

本文涉及的产品
资源编排,不限时长
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 编辑距离算法全解析:优化文本处理的关键技术

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

应用示例

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

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

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

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

相关文章
|
5天前
|
存储 关系型数据库 分布式数据库
PolarDB的PolarStore存储引擎以其高效的索引结构、优化的数据压缩算法、出色的事务处理能力著称
PolarDB的PolarStore存储引擎以其高效的索引结构、优化的数据压缩算法、出色的事务处理能力著称。本文深入解析PolarStore的内部机制及优化策略,包括合理调整索引、优化数据分布、控制事务规模等,旨在最大化其性能优势,提升数据存储与访问效率。
16 5
|
13天前
|
网络协议 网络安全 网络虚拟化
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算。通过这些术语的详细解释,帮助读者更好地理解和应用网络技术,应对数字化时代的挑战和机遇。
50 3
|
13天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
40 2
|
16天前
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
55 3
|
18天前
|
Kubernetes Cloud Native 云计算
云原生技术深度解析:重塑企业IT架构的未来####
本文深入探讨了云原生技术的核心理念、关键技术组件及其对企业IT架构转型的深远影响。通过剖析Kubernetes、微服务、容器化等核心技术,本文揭示了云原生如何提升应用的灵活性、可扩展性和可维护性,助力企业在数字化转型中保持领先地位。 ####
|
19天前
|
自然语言处理 并行计算 数据可视化
免费开源法律文档比对工具:技术解析与应用
这款免费开源的法律文档比对工具,利用先进的文本分析和自然语言处理技术,实现高效、精准的文档比对。核心功能包括文本差异检测、多格式支持、语义分析、批量处理及用户友好的可视化界面,广泛适用于法律行业的各类场景。
|
3天前
|
存储 供应链 算法
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
15 0
|
4天前
|
机器学习/深度学习 人工智能 自然语言处理
探索深度学习与自然语言处理的前沿技术:Transformer模型的深度解析
探索深度学习与自然语言处理的前沿技术:Transformer模型的深度解析
21 0
|
13天前
|
存储 供应链 物联网
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
|
13天前
|
存储 供应链 安全
深度解析区块链技术的核心原理与应用前景
深度解析区块链技术的核心原理与应用前景
22 0

推荐镜像

更多
下一篇
无影云桌面