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

2024-04-27 10:04

本文主要是介绍编辑距离算法全解析:优化文本处理的关键技术,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者介绍: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] = ifor j in range(1, n + 1):dp[0][j] = jfor 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]) + 1return 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, word1m, n = len(word1), len(word2)previous, current = list(range(n + 1)), [0] * (n + 1)for i in range(1, m + 1):current[0] = ifor 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]) + 1previous, current = current, previousreturn 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 jif j == 0: return iif 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)) + 1memo[(i, j)] = ansreturn ansreturn 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] = ifor j in range(n + 1):dp[0][j] = jfor 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]) + 1return 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] = ifor j in range(n + 1):dp[0][j] = jfor 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) + 1return 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))
优势易于理解和实现空间复杂度较低避免重复计算,提高效率适合大规模数据处理直观反映不同编辑操作
劣势空间占用大代码稍复杂空间占用大空间占用大实现较为复杂

应用示例

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

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

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

这篇关于编辑距离算法全解析:优化文本处理的关键技术的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940201

相关文章

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

解析 XML 和 INI

XML 1.TinyXML库 TinyXML是一个C++的XML解析库  使用介绍: https://www.cnblogs.com/mythou/archive/2011/11/27/2265169.html    使用的时候,只要把 tinyxml.h、tinystr.h、tinystr.cpp、tinyxml.cpp、tinyxmlerror.cpp、tinyxmlparser.

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

tf.split()函数解析

API原型(TensorFlow 1.8.0): tf.split(     value,     num_or_size_splits,     axis=0,     num=None,     name='split' ) 这个函数是用来切割张量的。输入切割的张量和参数,返回切割的结果。  value传入的就是需要切割的张量。  这个函数有两种切割的方式: 以三个维度的张量为例,比如说一

大林 PID 算法

Dahlin PID算法是一种用于控制和调节系统的比例积分延迟算法。以下是一个简单的C语言实现示例: #include <stdio.h>// DALIN PID 结构体定义typedef struct {float SetPoint; // 设定点float Proportion; // 比例float Integral; // 积分float Derivative; // 微分flo

服务器雪崩的应对策略之----SQL优化

SQL语句的优化是数据库性能优化的重要方面,特别是在处理大规模数据或高频访问时。作为一个C++程序员,理解SQL优化不仅有助于编写高效的数据库操作代码,还能增强对系统性能瓶颈的整体把握。以下是详细的SQL语句优化技巧和策略: SQL优化 1. 选择合适的数据类型2. 使用索引3. 优化查询4. 范式化和反范式化5. 查询重写6. 使用缓存7. 优化数据库设计8. 分析和监控9. 调整配置1、

Java中如何优化数据库查询性能?

Java中如何优化数据库查询性能? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨在Java中如何优化数据库查询性能,这是提升应用程序响应速度和用户体验的关键技术。 优化数据库查询性能的重要性 在现代应用开发中,数据库查询是最常见的操作之一。随着数据量的增加和业务复杂度的提升,数据库查询的性能优化显得尤为重

GaussDB关键技术原理:高性能(二)

GaussDB关键技术原理:高性能(一)从数据库性能优化系统概述对GaussDB的高性能技术进行了解读,本篇将从查询处理综述方面继续分享GaussDB的高性能技术的精彩内容。 2 查询处理综述 内容概要:本章节介绍查询端到端处理的执行流程,首先让读者对查询在数据库内部如何执行有一个初步的认识,充分理解查询处理各阶段主要瓶颈点以及对应的解决方案,本章以GaussDB为例讲解查询执行的几个主要阶段

陀螺仪LSM6DSV16X与AI集成(8)----MotionFX库解析空间坐标

陀螺仪LSM6DSV16X与AI集成.8--MotionFX库解析空间坐标 概述视频教学样品申请源码下载开启CRC串口设置开启X-CUBE-MEMS1设置加速度和角速度量程速率选择设置FIFO速率设置FIFO时间戳批处理速率配置过滤链初始化定义MotionFX文件卡尔曼滤波算法主程序执行流程lsm6dsv16x_motion_fx_determin欧拉角简介演示 概述 本文将探讨