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 求解编辑距离问题(动态规划法)…...

搭建android开发环境 android studio
1、环境介绍 在进行安卓开发时,需要掌握java,需要安卓SDK,需要一款编辑器,还需要软件的测试环境(真机或虚拟机)。 早起开发安卓app,使用的是eclipse加安卓SDK,需要自行搭建。 目前开…...

R语言6种将字符转成数字的方法,写在新年来临之际
咱们临床研究中,拿到数据后首先要对数据进行清洗,把数据变成咱们想要的格式,才能进行下一步分析,其中数据中的字符转成数字是个重要的内容,因为字符中常含有特殊符号,不利于分析,转成数字后才能…...

RocketMQ学习笔记(持续更新中......)
目录 1. 单机搭建 2. 测试RocketMQ 3. 集群搭建 4. 集群启动 5. RocketMQ-DashBoard搭建 6. 不同类型消息发送 1.同步消息 2. 异步消息发送 3. 单向发送消息 7. 消费消息 1. 单机搭建 1. 先从rocketmq官网下载二进制包,ftp上传至linux服务器,…...

强化学习的基础概念
这节课会介绍一些基本的概念,并结合例子讲解。 在马尔科夫决策框架下介绍这些概念 本博客是基于西湖大学强化学习课程的视屏进行笔记的,这是链接: 课程链接 目录 强化学习的基本概念 state和state space Action和Action Space State transiti…...

excel怎么删除右边无限列(亲测有效)
excel怎么删除右边无限列(亲测有效) 网上很多只用第1步的,删除了根本没用,还是存在,但是隐藏后取消隐藏却是可以的。 找到右边要删除的列的第一个空白列,选中整个列按“ctrlshift>(向右的小箭头)”&am…...

STM32-笔记23-超声波传感器HC-SR04
一、简介 HC-SR04 工作参数: • 探测距离:2~600cm • 探测精度:0.1cm1% • 感应角度:<15 • 输出方式:GPIO • 工作电压:DC 3~5.5V • 工作电流:5.3mA • 工作温度:-40~85℃ 怎么…...

Linux | Ubuntu零基础安装学习cURL文件传输工具
目录 介绍 检查安装包 下载安装 手册 介绍 cURL是一个利用URL语法在命令行下工作的文件传输工具,首次发行于1997年12。cURL支持多种协议,包括FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3…...

什么是 GPT?Transformer 工作原理的动画展示
大家读完觉得有意义记得关注和点赞!!! 目录 1 图解 “Generative Pre-trained Transformer”(GPT) 1.1 Generative:生成式 1.1.1 可视化 1.1.2 生成式 vs. 判别式(译注) 1.2 Pr…...

SpringCloudAlibaba实战入门之路由网关Gateway过滤器(十三)
承接上篇,我们知道除了断言,还有一个重要的功能是过滤器,本节课我们就讲一下常见的网关过滤器及其一般使用。 一、Filter介绍 类似SpringMVC里面的的拦截器Interceptor,Servlet的过滤器。“pre”和“post”分别会在请求被执行前调用和被执行后调用,用来修改请求和响应信…...

电路仿真软件PSIM简介
在从事开关电源相关产品开发的工程师或者正在学习开关电源的学习者,常常会用到各种仿真软件进行电路的仿真,不仅可以快速验证电路参数,还能清楚知道各器件的工作状态。 现在的电路仿真软件很多,例如matlab、Multisim、Simplis&…...