一个快速、高效的Levenshtein算法实现
转自:http://www.cnblogs.com/ymind/archive/2012/03/27/fast-memory-efficient-Levenshtein-algorithm.html
Levenshtein算法,用于计算两个字符串之间的Levenshtein距离。而Levenshtein距离又称为编辑距离,是指两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
概述
Levenshtein距离用来描述两个字符串之间的差异。我在一个网络爬虫程序里面使用这个算法来比较两个网页之间的版本,如果网页的内容有足够多的变动,我便将它更新到我的数据库。
说明
原来的算法是创建一个大小为StrLen1*StrLen2的矩阵。如果所有字符串加起来是1000个字符那么长的话,那么这个矩阵就会是1M;如果字符串是10000个字符,那么矩阵就是100M。如果元素都是整数(这里是指数字,Int32)的话,那么矩阵就会是4*100M == 400MB这么大,唉……
现在的算法版本只使用2*StrLen个元素,这使得后面给出的例子成为2*10,000*4 = 80 KB。其结果是,不但内存占用更少,而且速度也变快了!因为这使得内存分配只需要很少的时间来完成。当两个字符串的长度都是1k左右时,新算法的效率是旧算法的两倍!
示例
原来的版本将会创建一个矩阵[6+1, 5+1],而我的新算法将会创建两个向量[6+1](黄色元素)。在这两个算法版本中,字符串的顺序是无关紧要、无所谓的,也就是说,它也可以是矩阵[5+1, 6+1]和两个向量[5+1]。
新的算法
步骤
| 步骤 | 说明 |
|---|---|
| 1 | 设置n为字符串s的长度。("GUMBO") 设置m为字符串t的长度。("GAMBOL") 如果n等于0,返回m并退出。 如果m等于0,返回n并退出。 构造两个向量v0[m+1] 和v1[m+1],串联0..m之间所有的元素。 |
| 2 | 初始化 v0 to 0..m。 |
| 3 | 检查 s (i from 1 to n) 中的每个字符。 |
| 4 | 检查 t (j from 1 to m) 中的每个字符 |
| 5 | 如果 s[i] 等于 t[j],则编辑代价为 0; 如果 s[i] 不等于 t[j],则编辑代价为1。 |
| 6 | 设置单元v1[j]为下面的最小值之一: a、紧邻该单元上方+1:v1[j-1] + 1 b、紧邻该单元左侧+1:v0[j] + 1 c、该单元对角线上方和左侧+cost:v0[j-1] + cost |
| 7 | 在完成迭代 (3, 4, 5, 6) 之后,v1[m]便是编辑距离的值。 |
本小节将演示如何计算"GUMBO"和"GAMBOL"两个字符串的Levenshtein距离。
步骤1、2
| v0 | v1 | |||||
| G | U | M | B | O | ||
| 0 | 1 | 2 | 3 | 4 | 5 | |
| G | 1 | |||||
| A | 2 | |||||
| M | 3 | |||||
| B | 4 | |||||
| O | 5 | |||||
| L | 6 |
步骤3-6,当 i = 1
| v0 | v1 | |||||
| G | U | M | B | O | ||
| 0 | 1 | 2 | 3 | 4 | 5 | |
| G | 1 | 0 | ||||
| A | 2 | 1 | ||||
| M | 3 | 2 | ||||
| B | 4 | 3 | ||||
| O | 5 | 4 | ||||
| L | 6 | 5 |
步骤3-6,当 i = 2
| v0 | v1 | |||||
| G | U | M | B | O | ||
| 0 | 1 | 2 | 3 | 4 | 5 | |
| G | 1 | 0 | 1 | |||
| A | 2 | 1 | 1 | |||
| M | 3 | 2 | 2 | |||
| B | 4 | 3 | 3 | |||
| O | 5 | 4 | 4 | |||
| L | 6 | 5 | 5 |
步骤3-6,当 i = 3
| v0 | v1 | |||||
| G | U | M | B | O | ||
| 0 | 1 | 2 | 3 | 4 | 5 | |
| G | 1 | 0 | 1 | 2 | ||
| A | 2 | 1 | 1 | 2 | ||
| M | 3 | 2 | 2 | 1 | ||
| B | 4 | 3 | 3 | 2 | ||
| O | 5 | 4 | 4 | 3 | ||
| L | 6 | 5 | 5 | 4 |
步骤3-6,当 i = 4
| v0 | v1 | |||||
| G | U | M | B | O | ||
| 0 | 1 | 2 | 3 | 4 | 5 | |
| G | 1 | 0 | 1 | 2 | 3 | |
| A | 2 | 1 | 1 | 2 | 3 | |
| M | 3 | 2 | 2 | 1 | 2 | |
| B | 4 | 3 | 3 | 2 | 1 | |
| O | 5 | 4 | 4 | 3 | 2 | |
| L | 6 | 5 | 5 | 4 | 3 |
步骤3-6,当 i = 5
| v0 | v1 | |||||
| G | U | M | B | O | ||
| 0 | 1 | 2 | 3 | 4 | 5 | |
| G | 1 | 0 | 1 | 2 | 3 | 4 |
| A | 2 | 1 | 1 | 2 | 3 | 4 |
| M | 3 | 2 | 2 | 1 | 2 | 3 |
| B | 4 | 3 | 3 | 2 | 1 | 2 |
| O | 5 | 4 | 4 | 3 | 2 | 1 |
| L | 6 | 5 | 5 | 4 | 3 | 2 |
步骤7
编辑距离就是矩阵右下角的值,v1[m] == 2。由"GUMBO"变换为"GAMBOL"的过程对于我来说是很只管的,即通过将"A"替换为"U",并在末尾追加"L"这样子(实际上替换的过程是由移除和插入两个操作组合而成的)。
改良
如果您确信你的字符串永远不会超过2^16(65536)个字符,那么你可以使用ushort来表示而不是int,如果字符串少于2^8个,还可以使用byte。我觉得这个算法用非托管代码实现的话可能会更快,但我没有试过。
参考文献
下载代码请前往原文:http://www.codeproject.com/Articles/13525/Fast-memory-efficient-Levenshtein-algorithm
一个快速、高效的Levenshtein算法实现的更多相关文章
- 一个快速、高效的Levenshtein算法实现——代码实现
在网上看到一篇博客讲解Levenshtein的计算,大部分内容都挺好的,只是在一些细节上不够好,看了很长时间才明白.我对其中的算法描述做了一个简单的修改.原文的链接是:一个快速.高效的Levensht ...
- 如何快速高效地完成一个Android项目?
本文的内容有别于之前文章中纯技术的探讨,会从业务逻辑.技术.团队和方法论的角度探讨如何快速高效地完成一个Android项目.当然,快速高效是有前提的,第一,本文依然是从研发的角度来谈如何把控项目的,而 ...
- 【译】快速高效学习Java编程在线资源Top 20
想要加强你的编程能力吗?想要提升你的 Java 编程技巧和效率吗? 不用担心.本文将会提供快速高效学习 Java 编程的 50 多个网站资源: 开始探索吧: 1.MKyong:许多开发者在这里可以找到 ...
- 软阈值迭代算法(ISTA)和快速软阈值迭代算法(FISTA)
缺月挂疏桐,漏断人初静. 谁见幽人独往来,缥缈孤鸿影. 惊起却回头,有恨无人省. 拣尽寒枝不肯栖,寂寞沙洲冷.---- 苏轼 更多精彩内容请关注微信公众号 "优化与算法" ISTA ...
- 快速高效学习Java编程在线资源Top 20(转载)
想要加强你的编程能力吗?想要提升你的 Java 编程技巧和效率吗? 不用担心.本文将会提供快速高效学习 Java 编程的 50 多个网站资源: 开始探索吧: 1.MKyong:许多开发者在这里可以找到 ...
- 【转】C语言快速幂取模算法小结
(转自:http://www.jb51.net/article/54947.htm) 本文实例汇总了C语言实现的快速幂取模算法,是比较常见的算法.分享给大家供大家参考之用.具体如下: 首先,所谓的快速 ...
- FoxOne---一个快速高效的BS框架--WEB控件属性编辑器
FoxOne---一个快速高效的BS框架--(1) FoxOne---一个快速高效的BS框架--(2) FoxOne---一个快速高效的BS框架--(3) FoxOne---一个快速高效的BS框架-- ...
- FoxOne---一个快速高效的BS框架--(4)
FoxOne---一个快速高效的BS框架--(1) FoxOne---一个快速高效的BS框架--(2) FoxOne---一个快速高效的BS框架--(3) FoxOne---一个快速高效的BS框架-- ...
- FoxOne---一个快速高效的BS框架--(2)
FoxOne---一个快速高效的BS框架--(1) FoxOne---一个快速高效的BS框架--(2) FoxOne---一个快速高效的BS框架--(3) FoxOne---一个快速高效的BS框架-- ...
随机推荐
- WebService中方法的相关注意事项
2014-11-14 在WebService中定义方法,有一些注意的地方: (1) 方法上面需要增加 [WebMethod] 属性,标志该方法是一个WebService方法: (2)方法的返回值可以为 ...
- android-android各大手机系统打开权限管理页面
android系统五花八门,当我们去请求用户的权限的时候,总是会弹出是否允许的对话框. 而且用户一旦不小心点了拒绝,下次就不再询问了,而很多小白用户也不知道怎么去设置.这就导致了很不好的用户体验. 经 ...
- c++中try catch的用法
c++中try catch的用法 标签: c++exception数据库sqlc 2011-10-24 21:49 45622人阅读 评论(3) 收藏 举报 分类: 一点小结(267) 版权声明: ...
- jQuery.snowflake雪花飘落插件
一.前言 前言:最近圣诞节来临,需要在页面上应用一个雪花飘落的效果,做之前产品经理给了我网络上的一个demo,地址是http://demo.lanrenzhijia.com/demo/1225/sd/ ...
- dedecms文章标题是在哪个数据库表?要批量替换关键词
一位小MM刚接触dedecms没多久还不熟悉后台的操作,她说改dedecms文章中的品牌名改到手酸,问ytkah是否有批量替换关键词的方法,教了她dedecms后台批量替换文章中的关键词方法,她高兴坏 ...
- linux配置ant
第1步:下载ant ,地址:http://ftp.twaren.net/Unix/Web/apache//ant/binaries/apache-ant-1.9.6-bin.tar.gz apache ...
- [Effective JavaScript 笔记] 第14条:当心命名函数表达式笨拙的作用域
js函数会根据上下文改变其含义. function double(x){return x*2;} 这是一个函数声明,也可以是一个命名函数表达式(named function expression),取 ...
- 让jar程序在linux上一直执行
当我们把java程序打成jar包后,放到linux上通过putty或其它终端执行的时候,如果按照:java -jar xxxx.jar执行,当我们退出putty或终端的时候,xxxx.jar这个程序也 ...
- 【OpenStack】OpenStack系列17之OpenStack私有云设计二
- div设置边框黑框显示
style="width:756px; height:68px; border:1px solid #000000;"