Levenshtein 距离的原理与应用
引言
在文本处理和自然语言处理(NLP)中,衡量两个字符串相似度是一项重要任务。Levenshtein 距离(也称编辑距离)是一种常见的算法,用于计算将一个字符串转换为另一个字符串所需的最少编辑操作次数。这些操作包括插入、删除和替换。
本文将详细介绍 Levenshtein 距离的原理,并通过 Python 代码示例展示其实际应用。
什么是 Levenshtein 距离?
Levenshtein 距离定义为两个字符串之间的最小编辑操作次数,使得一个字符串可以变为另一个字符串。允许的三种操作为:
- 插入一个字符;
- 删除一个字符;
- 替换一个字符。
例如:
"kitten"和"sitting"的 Levenshtein 距离为 3,因为可以通过以下三步完成转换:- 替换
'k'为's'; - 替换
'e'为'i'; - 在末尾插入
'g'。
- 替换
Levenshtein 距离的计算原理
Levenshtein 距离使用动态规划(Dynamic Programming)实现,其核心思想是将问题分解为多个子问题,通过递归公式逐步计算解决。
假设字符串 AA 长度为 mm,字符串 BB 长度为 nn,则动态规划表 dp[i][j]dp[i][j] 表示将 A[0:i]A[0:i] 转换为 B[0:j]B[0:j] 的最小编辑距离。
Levenshtein 距离的 Python 实现
我们用一个简单的 Python 函数实现 Levenshtein 距离:
def levenshtein_distance(a, b):m, n = len(a), len(b)# 初始化动态规划表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] = j# 计算动态规划表for i in range(1, m + 1):for j in range(1, n + 1):cost = 0 if a[i - 1] == b[j - 1] else 1dp[i][j] = min(dp[i - 1][j] + 1, # 删除dp[i][j - 1] + 1, # 插入dp[i - 1][j - 1] + cost # 替换)return dp[m][n]# 示例
a = "kitten"
b = "sitting"
distance = levenshtein_distance(a, b)
print(f"'{a}' 和 '{b}' 的 Levenshtein 距离为: {distance}")
运行结果:
'kitten' 和 'sitting' 的 Levenshtein 距离为: 3
Levenshtein 距离的应用场景
-
拼写纠错
- Levenshtein 距离可用于计算用户输入与正确单词之间的相似度,从而推荐正确的单词。
- 例如输入
"recieve",通过计算与候选词的距离,可以推荐"receive"。
-
模糊匹配
- 在数据库中模糊查找类似记录,比如搜索
"Jon"时匹配"John"。 - 使用 Python 的 TheFuzz 库可以轻松实现。
- 在数据库中模糊查找类似记录,比如搜索
-
文本去重
- 用于检测相似文本并去重,例如处理社交媒体内容或产品描述。
-
DNA 序列比对
- Levenshtein 距离在生物信息学中也有重要应用,用于比较 DNA 或 RNA 序列的相似性。
使用 Python 库快速计算 Levenshtein 距离
除了手动实现外,我们还可以使用开源库 Levenshtein 或 TheFuzz 快速计算。
安装:
pip install python-Levenshtein
示例代码:
import Levenshteina = "kitten"
b = "sitting"
distance = Levenshtein.distance(a, b)
print(f"'{a}' 和 '{b}' 的 Levenshtein 距离为: {distance}")
结果:
'kitten' 和 'sitting' 的 Levenshtein 距离为: 3
总结
Levenshtein 距离是一种高效且实用的字符串相似度度量方法。通过动态规划算法实现,它在拼写纠错、模糊匹配和文本去重等领域得到了广泛应用。无论是从学习算法原理,还是通过现有库快速应用,Levenshtein 距离都能为开发者带来极大帮助。
其它
多个字符串比较的例子 (比较字符串(i love you )和(love he))
我们利用动态规划的方式,逐步计算字符串 "i love you " 和 "love he " 的 Levenshtein 距离,以下是详细的过程。
1. 初始化动态规划表
假设:
- A="iloveyou"A = "i love you "(长度为 10,包括空格)
- B="lovehe"B = "love he "(长度为 8,包括空格)
动态规划表 dpdp 大小为 (10+1)×(8+1)=11×9(10+1) \times (8+1) = 11 \times 9。
初始状态如下:
- 第一行填充列索引(从空字符串到
B的编辑距离) - 第一列填充行索引(从空字符串到
A的编辑距离)
| l | o | v | e | h | e | |||
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
| i | 1 | |||||||
| 2 | ||||||||
| l | 3 | |||||||
| o | 4 | |||||||
| v | 5 | |||||||
| e | 6 | |||||||
| 7 | ||||||||
| y | 8 | |||||||
| o | 9 | |||||||
| u | 10 |
2. 填充动态规划表
根据递归公式:
dp[i][j]=min{dp[i−1][j]+1,删除dp[i][j−1]+1,插入dp[i−1][j−1]+cost,替换dp[i][j] = \min \begin{cases} dp[i-1][j] + 1, & \text{删除} \\ dp[i][j-1] + 1, & \text{插入} \\ dp[i-1][j-1] + \text{cost}, & \text{替换} \end{cases}
其中:
- 如果 A[i−1]=B[j−1]A[i-1] = B[j-1],则 cost=0\text{cost} = 0,否则 cost=1\text{cost} = 1。
填充过程:
-
i=1,j=1i = 1, j = 1(比较
'i'和'l'):- 插入:dp[1][0]+1=2dp[1][0] + 1 = 2
- 删除:dp[0][1]+1=2dp[0][1] + 1 = 2
- 替换:dp[0][0]+1=1dp[0][0] + 1 = 1
所以 dp[1][1]=1dp[1][1] = 1。
-
i=1,j=2i = 1, j = 2(比较
'i'和'o'):- 插入:dp[1][1]+1=2dp[1][1] + 1 = 2
- 删除:dp[0][2]+1=3dp[0][2] + 1 = 3
- 替换:dp[0][1]+1=2dp[0][1] + 1 = 2
所以 dp[1][2]=2dp[1][2] = 2。
... 依此类推。
最终动态规划表填充完成后如下:
| l | o | v | e | h | e | |||
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
| i | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 2 | 2 | 2 | 3 | 4 | 4 | 5 | 6 | |
| l | 3 | 2 | 3 | 3 | 4 | 5 | 5 | 6 |
| o | 4 | 3 | 2 | 3 | 4 | 5 | 6 | 6 |
| v | 5 | 4 | 3 | 2 | 3 | 4 | 5 | 6 |
| e | 6 | 5 | 4 | 3 | 2 | 3 | 4 | 5 |
| 7 | 6 | 5 | 4 | 3 | 2 | 3 | 4 | |
| y | 8 | 7 | 6 | 5 | 4 | 3 | 3 | 4 |
| o | 9 | 8 | 7 | 6 | 5 | 4 | 4 | 4 |
| u | 10 | 9 | 8 | 7 | 6 | 5 | 5 | 5 |
3. 结果
表格右下角的值 dp[10][8]=5dp[10][8] = 5,表示将 "i love you " 转换为 "love he " 需要 5次编辑操作。
4. 操作过程
通过回溯动态规划表,我们可以得到具体的编辑操作:
- 删除
'i'(从'i love you '中删除第一个字符) - 替换
'y'为'h' - 替换
'o'为'e' - 删除
' '(去掉额外的空格) - 删除
'u'
最终,得到字符串 "love he "。
相关文章:
Levenshtein 距离的原理与应用
引言 在文本处理和自然语言处理(NLP)中,衡量两个字符串相似度是一项重要任务。Levenshtein 距离(也称编辑距离)是一种常见的算法,用于计算将一个字符串转换为另一个字符串所需的最少编辑操作次数。这些操作…...
解决json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
前言 作者在读取json文件的时候出现上述报错,起初以为是自己json文件有问题,但借助在线工具查看后发现没问题,就卡住了,在debug的过程中发现了json文件读取的一个小坑,在此分享一下 解决过程 原代码 with open(anno…...
hive中的四种排序类型
1、Order by 全局排序 ASC(ascend): 升序(默认) DESC(descend): 降序 注意 :只有一个 Reducer,即使我们在设置set reducer的数量为多个,但是在执行了order by语句之后,当前此次的运算还是只有…...
Spring-AI讲解
Spring-AI langchain(python) langchain4j 官网: https://spring.io/projects/spring-ai#learn 整合chatgpt 前置准备 open-ai-key: https://api.xty.app/register?affPuZD https://xiaoai.plus/ https://eylink.cn/ 或者淘宝搜: open ai key魔法…...
【brew安装失败】DNS 查询 raw.githubusercontent.com 返回的是 0.0.0.0
从你提供的 nslookup 输出看,DNS 查询 raw.githubusercontent.com 返回的是 0.0.0.0,这通常意味着无法解析该域名或该域名被某些 DNS 屏蔽了。这种情况通常有几个可能的原因: 可能的原因和解决方法 本地 DNS 问题: 有可能是你的本…...
HTML——29. 音频引入二
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>音频引入</title></head><body><!--audio:在网页中引入音频IE8以及之前版本不支持属性名和属性值一样,可以只写属性名src属性:指定音频文件…...
代码随想录训练营第三十四天| 62.不同路径 63. 不同路径 II
62.不同路径 题目链接:62. 不同路径 - 力扣(LeetCode) 讲解链接:代码随想录 动态规划五步走 1 定义dp数组是到dp[i][j]时有dp[i][j]条路径 dp[i][j] :表示从(0 ,0)出发…...
V90伺服PN版组态配置<一>
1、添加PLC之后,继续博图中网络视图中添加新设备,添加伺服驱动器组态设备 2、SINAMICS V90 PN V1.0 3、修改驱动器的IP地址。 【注意】 在项目中提前做好项目规划,如PLC设备从192.168.0.1开始,顺序递增------个位数都是CPU设备…...
又一年。。。。。。
2024,浑浑噩噩的一年。 除了100以内的加减法(数据,数据,还是数据。。。。。。),似乎没做些什么。 脸盲症越来越重的,怕是哪天连自己都不认得自己的了。 看到什么,听到什…...
xterm + vue3 + websocket 终端界面
xterm.js 下载插件 // xterm npm install --save xterm// xterm-addon-fit 使终端适应包含元素 npm install --save xterm-addon-fit// xterm-addon-attach 通过websocket附加到运行中的服务器进程 npm install --save xterm-addon-attach <template><div :…...
医疗数仓业务数据采集与同步
业务数据采集与同步 业务采集组件配置业务数据同步概述数据同步策略选择数据同步工具概述1.1.4 全量表数据同步DataX配置文件生成全量表数据同步脚本增量表数据同步 MySQL - Maxwell - Kafka - Flume - HDFSMaxwell配置增量表首日全量同步 业务采集组件配置 Maxwell将业务采集到…...
数字孪生智慧水利与水务所包含的应用场景有哪些?二者有何区别
水利和水务是两个密切相关但有所区别的概念,它们在水资源管理和保护方面各自承担着不同的职责和功能。 定义 智慧水务:智慧水务是指通过物联网、大数据、云计算、人工智能等新一代信息技术,对城市供水、排水、污水处理、水质监测等水务系统…...
Qt Creator项目构建配置说明
QT安装好之后,在安装目录的Tools\QtCreator\bin下找到qtcreator.exe文件并双击打开 点击文件-新建文件或项目 选择Qt Widgets Application 设置项目名称以及路径 make工具选择qmake(cmake还未尝试过) 设置主界面对应类的名称、父类&#…...
进程间通信的“五大武器”
😄作者简介: 小曾同学.com,一个致力于测试开发的博主⛽️,主要职责:测试开发、CI/CD 如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。 😊 座右铭:不…...
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之循环结构(for循环语句)(六)
实战训练1—输出九九乘法表 问题描述: 在学校里学过九九乘法表,编程实现打印九九乘法表。 输入格式: 无输入 输出格式: 1*11 2*12 2*24 3*13 3*26 3*39 4*14 4*28 4*312 4*416 5*15 5*210 5*315 5*420 5*525 6*16 6*212 6*318 6*424 6*5…...
封装echarts成vue component
封装echarts成vue component EChartsLineComponent 文章目录 封装echarts成vue component EChartsLineComponent封装说明重写重点EChartsLineComponent的源码 使用说明调用EChartsLineComponent示例源码 封装说明 为了减少一些公共代码和方便使用echarts的line图形,…...
uniapp Stripe 支付
引入 Stripe npm install stripe/stripe-js import { loadStripe } from stripe/stripe-js; Stripe 提供两种不同类型组件 Payment Element 和 Card Element:如果你使用的是 Payment Element,它是一个更高级别的组件,能够自动处理多种支…...
Windows onnxruntime编译openvino
理论上来说,可以直接访问 ONNXRuntime Releases 下载 dll 文件,然后从官方文档中下载缺少的头文件以直接调用,但我没有尝试过。 1. 下载 OpenVINO 包 从官网下载 OpenVINO 的安装包并放置在 C:\Program Files (x86) 路径下,例如…...
vue3+TS+vite中Echarts的安装与使用
概述 技术栈:Vue3TsViteEcharts 简述:图文详解,教你如何在Vue项目中引入Echarts,封装Echarts组件,并实现常用Echats图列 文章目录 一,效果图 二,引入Echarts 2.1安装Echarts 2.2main.ts中引…...
期末算法分析程序填空题
目录 5-1 最小生成树(普里姆算法) 5-2 快速排序(分治法) 输入样例: 输出样例: 5-3 归并排序(递归法) 输入样例: 输出样例: 5-4 求解编辑距离问题(动态规划法)…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
