Levenshtein编辑距离算法的改进—剪枝优化

  我们在先前的一篇博客中已经阐明了Levenshtein编辑距离算法,首先介绍算法的思想,后来介绍了根据跳转列表生成所有编辑方案的方法,并通过附带的代码来实现这些方法。本文中我们继续探讨Levenshtein编辑距离算法,引入了剪枝思想来更高效的生成编辑距离状态表。

  首先我们给出一张编辑距离表,如下所示:

Edit-Dist <\b> k i t t e n
<\b> 0 1 2 3 4 5 6
s 1 1 2 3 4 5 6
i 2 2 1 2 3 4 5
t 3 3 2 1 2 3 4
t 4 4 3 2 1 2 3
i 5 5 4 3 2 2 3
n 6 6 5 4 3 3 2
g 7 7 6 5 4 4 3

  我们通过观察表格不难发现,表格位于右上角和左下角附近的元素是不是都较大?这是因为右上角附近的元素生成了较多的删除操作,而左下角的元素生成了较多的插入操作。我们将一个字符串编辑为另一个字符串时,通过一个“替换”操作可以实现“先插入,后删除”或“先删除,后插入”这两种操作,因此替换操作是能够节省编辑步数的。读者可以从表格中发现,右上角和左下角附近的值往往在向右下角前进时会被其他元素所替代,即它们迭代过程中往往都不能成为最小元素。因此我们介绍一种Levenshtein编辑距离算法的剪枝操作,以便在计算步数的时候不必考虑右上角、左下角附近的元素。

  读者不难想出,两个字符串的最小编辑距离有一个最大值—就是两个字符串中较长字符串的长度,无论字符串的内容如何变化,最小编辑距离都不会大于较长字符串长度的。因此,我们对编辑距离表中那些能够使最终编辑步数大于最大长度的编辑状态采取跳过措施。那么哪些位置的元素能够导致最终产生大于最大值的编辑距离呢?我们给出判断是否符合这一条件的计算公式:

mindist=∣2∗(j−i)+len(target)−len(source)∣mindist = |2*(j - i) +len(target) - len(source)|mindist=∣2∗(j−i)+len(target)−len(source)∣

  该公式的意义是:包含该位置操作的编辑步骤的最小编辑距离。其中i、j分别为表格的行列下标。判断是否跳过的方式为:当计算结果mindist大于较长的字符串时,该位置可以不必计算编辑距离。我们来举个例子,比如对于上述表格,给出下标[1][5](下标从数字部分算起),则我们计算穿过该位置的最小编辑距离过程如下:将该位置用一条左上-右下方向的斜线贯穿其方格对角线,该线穿过的所有单元格呈斜向排列,由于计算的是最小编辑距离,因此我们假设这些斜向排列的单元格的操作都为“跳过”,就不必将它们计入总数;我们需要计算的是该线穿过的第一行的单元格及左边的所有单元格(不包括0),以及穿过的最后一列单元格下边的所有单元格,如下图所示:

  我们需要计算的是蓝色方框中的单元格数量,每个单元格代表一次编辑操作,横向代表“删除操作”,纵向代表“插入操作。图中有9个单元格,则我们认为通过橘红色位置(即位置[1][5])的编辑步数最小为9步。在代码中我们使用上文给到的公式便能够方便地计算出每个单元格的“最小步数”值。由于[1][5]的“最小步数”值大于两个字符串较大的长度8,因此该位置可以不必计算编辑距离,也不必参与到后面编辑距离的计算。
  我们用紫色区域标示出上述表格的所有可不必计算距离的单元格,如下所示:

  不难看出,可不必计算距离的单元格在表格中都成较小的上下三角矩阵分布,当两个序列长度相差较小时,这两个半矩阵也会增大。当两个序列等长时,半矩阵的直角边长会达到序列的一半,继而可不必计算的元素会占到所有元素的1/4.

  我们给出剪枝后的算法实现代码,并使用“我不是药神”和“我是谁”测试输出结果,如下所示:

    def edit_distance_reduced(self, source, target):if len(target) == 0 and len(source) == 0:return 0row = []jump_row = []maxnum = max(len(source), len(target))for i in range(len(target) + 1):for j in range(len(source) + 1):if abs(2*(j - i) +len(target) - len(source)) > maxnum :row.append(maxnum+1)jump_row.append(['-'])continueif i == 0:row.append(j)if j == 0 :jump_row.append(['-'])else:jump_row.append(['→'])continueelif j == 0:row.append(i)jump_row.append(['↓'])continuerow.append(0)jump_row.append([])self.Matrix.append(row)self.jump.append(jump_row)jump_row = []row = []for i in range(1, len(target) + 1):for j in range(1, len(source) + 1):if self.Matrix[i][j] == maxnum + 1 :continueif target[i - 1] == source[j - 1]:edit = 0else:edit = 1self.Matrix[i][j] = min(self.Matrix[i - 1][j] + 1, self.Matrix[i][j - 1] + 1,self.Matrix[i - 1][j - 1] + edit)if self.Matrix[i][j] == self.Matrix[i - 1][j] + 1:self.jump[i][j].append('↓')if self.Matrix[i][j] == self.Matrix[i][j - 1] + 1:self.jump[i][j].append('→')if self.Matrix[i][j] == self.Matrix[i - 1][j - 1] and self.source[j - 1] == self.target[i - 1]:self.jump[i][j].append('↘')if self.Matrix[i][j] == self.Matrix[i - 1][j - 1] + 1 and self.source[j - 1] != self.target[i - 1]:self.jump[i][j].append('↘')for i in range(len(target) + 1):print(self.Matrix[i])for i in range(len(target) + 1):print(self.jump[i])


   注:代码既可以接受字符串输入,也能接受列表。

  输出的状态矩阵中,我们把可以跳过的位置用一个极大值表示(图中用的是较长序列+1),跳转矩阵中则用 ‘-’ 表示。最终的最小距离和方案也与未加剪枝的结果输出相同,表明我们的思想基本正确。

Levenshtein编辑距离算法的改进---剪枝优化相关推荐

  1. 实现 RSA 算法之改进和优化(第三章)(老物)

    第三章 如何改进和优化RSA算法 这章呢,我想谈谈在实际应用出现的问题和理解. 由于近期要开始各种忙了,所以写完这章后我短时间内也不打算出什么资料了=- =(反正平时就没有出资料的习惯.) 在讲第一章 ...

  2. 基于 Iterative 映射和单纯形法的改进灰狼优化算法-附代码

    基于 Iterative 映射和单纯形法的改进灰狼优化算法 文章目录 基于 Iterative 映射和单纯形法的改进灰狼优化算法 1.灰狼优化算法 2. 改进灰狼优化算法(SMIGWO) 2.1 混沌 ...

  3. 基于Cat混沌与高斯变异的改进灰狼优化算法-附代码

    基于Cat混沌与高斯变异的改进灰狼优化算法 文章目录 基于Cat混沌与高斯变异的改进灰狼优化算法 1.灰狼优化算法 2. 改进灰狼优化算法 2.1 混沌反向学习策略的种群初始化 2. 2 引入个体记忆 ...

  4. 改进灰狼优化算法在WSN节点部署中的应用

    文章目录 一.理论基础 1.节点与覆盖模型 2.灰狼优化算法基本原理 3.改进灰狼优化算法 (1)非线性收敛因子 (2)δ\deltaδ狼的融合变异 二.节点部署优化算法 1.算法步骤 2.算法流程图 ...

  5. Levenshtein distance 编辑距离算法

    这几天再看 virtrual-dom,关于两个列表的对比,讲到了 Levenshtein distance 距离,周末抽空做一下总结. Levenshtein Distance 介绍 在信息理论和计算 ...

  6. Levenshtein Distance算法(编辑距离算法)

    编辑距离 编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符, ...

  7. 深度优先搜索(DFS) 总结(算法+剪枝+优化总结)

    深度优先搜索(DFS) 总结(算法+剪枝+优化总结) 本文中会引用部分实例.文献资料来自不同的作者之手,由于资料整理比较困难,转载地址不在文中列举.如有侵权请联系我更换或删除!对于提供题解思路的各位大 ...

  8. 编辑距离算法和Levenshtein距离算法

    前言 最近在研究diff工具的实现,已经写了一个简单的demo,不过目前这个demo只是把Levenshtein距离算法的结果用Qt可视化了出来而已,还没有实用价值,界面如下: 各种diff工具的核心 ...

  9. Levenshtein 相似度算法——Levenshtein(编辑距离)

    https://www.iteye.com/blog/wdhdmx-1343856 原文讲的挺有道理的: 奇妙的地方就是将字符串的对比,转换为了数值之间的计算: 相似度算法--Levenshtein( ...

最新文章

  1. wxWidgets:wxWeakRef< T >类模板的用法
  2. Java 基础 - 各项集合实现
  3. java 类的实例化没有属性值,java – JsonMappingException:无法实例化类型的值没有single-long-arg构造函数/工厂方法...
  4. LeetCode 第 197 场周赛(468/5273,前8.88%)
  5. React 第十二章 React思想
  6. mbsfn子帧_LTE多媒体广播多播业务关键技术研究
  7. spring cloud 资源
  8. 在windows中用 netsh 命令修改ip地址网关和DNS等
  9. html邮箱留言板代码,求HTML留言板代码或模板?
  10. GitHub 上有哪些优秀的 Python 爬虫项目?
  11. java股票雪球数据接口_国内股票数据接口API(5分钟K线、日线)
  12. Mac 下如何解压 bin 文件
  13. 鼠标没有唤醒计算机功能,怎么设置碰到鼠标电脑不会唤醒亮起来
  14. 跨域问题的解决-gateway跨域接解决方案,使用CorsWebFilter
  15. 【chrome不能扩展程序怎么办】4步搞定安装导入扩展
  16. 1677 treecnt(贡献)
  17. anki 新的卡片类型_Anki选择题卡片制作详解
  18. 游戏专辑一 3D游戏碰撞之体素内存、效率优化(未完待续10/14)
  19. 2022G3锅炉水处理特种作业证考试题库及答案
  20. 熬夜程序猿的膳食调养

热门文章

  1. ofo回应2.5亿元诉讼,网友:“有生之年,我的押金能退吗?
  2. 无代码开发的五大好处
  3. iOS:iOS8开发(三)~深入理解autolayout
  4. 字符和字符串的区别和使用
  5. 关于voliate关键字
  6. 第二届日知录企业存储峰会落下帷幕
  7. 360应用开放平台很给力
  8. 盗梦空间(Inception)
  9. 超级技术:改变未来社会和商业的技术趋势
  10. 2014年QS亚洲最佳大学排行榜出炉 北大进前十