在日常应用中,文本比较是一个比较常见的问题。文本比较算法也是一个老生常谈的话题。

  文本比较的核心就是比较两个给定的文本(可以是字节流等)之间的差异。目前,主流的比较文本之间的差异主要有两大类。一类是基于编辑距离(Edit Distance)的,例如LD算法。一类是基于最长公共子串的(Longest Common Subsequence),例如Needleman/Wunsch算法等。

  LD算法(Levenshtein Distance)又成为编辑距离算法(Edit Distance)。他是以字符串A通过插入字符、删除字符、替换字符变成另一个字符串B,那么操作的过程的次数表示两个字符串的差异。

  例如:字符串A:kitten如何变成字符串B:sitting。

    第一步:kitten——》sitten。k替换成s

    第二步:sitten——》sittin。e替换成i

    第三步:sittin——》sitting。在末尾插入g

  故kitten和sitting的编辑距离为3

  定义说明:

  LD(A,B)表示字符串A和字符串B的编辑距离。很显然,若LD(A,B)=0表示字符串A和字符串B完全相同

  Rev(A)表示反转字符串A

  Len(A)表示字符串A的长度

  A+B表示连接字符串A和字符串B

  

  有下面几个性质:

  LD(A,A)=0

  LD(A,"")=Len(A)

  LD(A,B)=LD(B,A)

  0≤LD(A,B)≤Max(Len(A),Len(B))

  LD(A,B)=LD(Rev(A),Rev(B))

  LD(A+C,B+C)=LD(A,B)

  LD(A+B,A+C)=LD(B,C)

  LD(A,B)≤LD(A,C)+LD(B,C)(注:像不像“三角形,两边之和大于第三边”)

  LD(A+C,B)≤LD(A,B)+LD(B,C)

  为了讲解计算LD(A,B),特给予以下几个定义

  A=a1a2……aN,表示A是由a1a2……aN这N个字符组成,Len(A)=N

  B=b1b2……bM,表示B是由b1b2……bM这M个字符组成,Len(B)=M

  定义LD(i,j)=LD(a1a2……ai,b1b2……bj),其中0≤i≤N,0≤j≤M

  故:  LD(N,M)=LD(A,B)

      LD(0,0)=0

      LD(0,j)=j

      LD(i,0)=i

  对于1≤i≤N,1≤j≤M,有公式一

  若ai=bj,则LD(i,j)=LD(i-1,j-1)

  若ai≠bj,则LD(i,j)=Min(LD(i-1,j-1),LD(i-1,j),LD(i,j-1))+1

  举例说明:A=GGATCGA,B=GAATTCAGTTA,计算LD(A,B)

  第一步:初始化LD矩阵  

LD算法矩阵
    G A A T T C A G T T A
  0 1 2 3 4 5 6 7 8 9 10 11
G 1                      
G 2                      
A 3                      
T 4                      
C 5                      
G 6                      
A 7                      

  第二步:利用上述的公式一,计算第一行

LD算法矩阵
    G A A T T C A G T T A
  0 1 2 3 4 5 6 7 8 9 10 11
G 1 0 1 2 3 4 5 6 7 8 9 10
G 2                      
A 3                      
T 4                      
C 5                      
G 6                      
A 7                      

  第三步,利用上述的公示一,计算其余各行

LD算法矩阵
    G A A T T C A G T T A
  0 1 2 3 4 5 6 7 8 9 10 11
G 1 0 1 2 3 4 5 6 7 8 9 10
G 2 1 1 2 3 4 5 6 6 7 8 9
A 3 2 1 1 2 3 4 5 6 7 8 8
T 4 3 2 2 1 2 3 4 5 6 7 8
C 5 4 3 3 2 2 2 3 4 5 6 7
G 6 5 4 4 3 3 3 3 3 4 5 6
A 7 6 5 4 4 4 4 3 4 4 5 5

  则LD(A,B)=LD(7,11)=5

  下面是LD算法的代码,用的是VB2005。代码格式修正于2012年1月6日。

Public Class clsLD
  Private Shared mA() As Char
  Private Shared mB() As Char
  Public Shared Function LD(ByVal A As String, ByVal B As String) As Integer
    mA = A.ToCharArray
    mB = B.ToCharArray
    Dim L(A.Length, B.Length) As Integer
    Dim i As Integer, j As Integer
    For i = 1 To A.Length
      L(i, 0) = i
    Next
    For j = 1 To B.Length
      L(0, j) = j
    Next
    For i = 1 To A.Length
      For j = 1 To B.Length
        If mA(i - 1) = mB(j - 1) Then
          L(i, j) = L(i - 1, j - 1)
        Else
          L(i, j) = Min(L(i - 1, j - 1), L(i - 1, j), L(i, j - 1)) + 1
        End If
      Next
    Next
    Return L(A.Length, B.Length)
  End Function
  Public Shared Function Min(ByVal A As Integer, ByVal B As Integer, ByVal C As Integer) As Integer
    Dim I As Integer = A
    If I > B Then I = B
    If I > C Then I = C
    Return I
  End Function
End Class

  这个LD算法时间复杂度为O(MN),空间复杂度为O(MN),如果进行优化的话,空间复杂度可以为O(M),优化的代码这里不再详述了。参看“计算字符串的相似度(VB2005)”

  我们往往不仅仅是计算出字符串A和字符串B的编辑距离,还要能得出他们的匹配结果。

  以上面为例A=GGATCGA,B=GAATTCAGTTA,LD(A,B)=5

  他们的匹配为:

    A:GGA_TC_G__A

    B:GAATTCAGTTA

  如上面所示,蓝色表示完全匹配,黑色表示编辑操作,_表示插入字符或者是删除字符操作。如上面所示,黑色字符有5个,表示编辑距离为5。

  利用上面的LD矩阵,通过回溯,能找到匹配字串

  第一步:定位在矩阵的右下角  

LD算法矩阵
    G A A T T C A G T T A
  0 1 2 3 4 5 6 7 8 9 10 11
G 1 0 1 2 3 4 5 6 7 8 9 10
G 2 1 1 2 3 4 5 6 6 7 8 9
A 3 2 1 1 2 3 4 5 6 7 8 8
T 4 3 2 2 1 2 3 4 5 6 7 8
C 5 4 3 3 2 2 2 3 4 5 6 7
G 6 5 4 4 3 3 3 3 3 4 5 6
A 7 6 5 4 4 4 4 3 4 4 5 5

  第二步:回溯单元格,至矩阵的左上角

    若ai=bj,则回溯到左上角单元格

LD算法矩阵
    G A A T T C A G T T A
  0 1 2 3 4 5 6 7 8 9 10 11
G 1 0 1 2 3 4 5 6 7 8 9 10
G 2 1 1 2 3 4 5 6 6 7 8 9
A 3 2 1 1 2 3 4 5 6 7 8 8
T 4 3 2 2 1 2 3 4 5 6 7 8
C 5 4 3 3 2 2 2 3 4 5 6 7
G 6 5 4 4 3 3 3 3 3 4 5 6
A 7 6 5 4 4 4 4 3 4 4 5 5

    若ai≠bj,回溯到左上角、上边、左边中值最小的单元格,若有相同最小值的单元格,优先级按照左上角、上边、左边的顺序

LD算法矩阵
    G A A T T C A G T T A
  0 1 2 3 4 5 6 7 8 9 10 11
G 1 0 1 2 3 4 5 6 7 8 9 10
G 2 1 1 2 3 4 5 6 6 7 8 9
A 3 2 1 1 2 3 4 5 6 7 8 8
T 4 3 2 2 1 2 3 4 5 6 7 8
C 5 4 3 3 2 2 2 3 4 5 6 7
G 6 5 4 4 3 3 3 3 3 4 5 6
A 7 6 5 4 4 4 4 3 4 4 5 5

    若当前单元格是在矩阵的第一行,则回溯至左边的单元格

    若当前单元格是在矩阵的第一列,则回溯至上边的单元格

LD算法矩阵
    G A A T T C A G T T A
  0 1 2 3 4 5 6 7 8 9 10 11
G 1 0 1 2 3 4 5 6 7 8 9 10
G 2 1 1 2 3 4 5 6 6 7 8 9
A 3 2 1 1 2 3 4 5 6 7 8 8
T 4 3 2 2 1 2 3 4 5 6 7 8
C 5 4 3 3 2 2 2 3 4 5 6 7
G 6 5 4 4 3 3 3 3 3 4 5 6
A 7 6 5 4 4 4 4 3 4 4 5 5

    依照上面的回溯法则,回溯到矩阵的左上角

  第三步:根据回溯路径,写出匹配字串

    若回溯到左上角单元格,将ai添加到匹配字串A,将bj添加到匹配字串B

    若回溯到上边单元格,将ai添加到匹配字串A,将_添加到匹配字串B

    若回溯到左边单元格,将_添加到匹配字串A,将bj添加到匹配字串B

    搜索晚整个匹配路径,匹配字串也就完成了

  从上面可以看出,LD算法在不需要计算出匹配字串的话,时间复杂度为O(MN),空间复杂度经优化后为O(M)

  不过,如果要计算匹配字符串的话,时间复杂度为O(MN),空间复杂度由于需要利用LD矩阵计算匹配路径,故空间复杂度仍然为O(MN)。这个在两个字符串都比较短小的情况下,能获得不错的性能。不过,如果字符串比较长的情况下,就需要极大的空间存放矩阵。例如:两个字符串都是20000字符,则LD矩阵的大小为20000*20000*2=800000000Byte=800MB。呵呵,这是什么概念?故,在比较长字符串的时候,还有其他性能更好的算法。留待后文详述。

作者:万仓一黍
出处:http://grenet.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

文本比较算法Ⅰ——LD算法相关推荐

  1. 基因序列算法:编辑距离( Levenshtein 距离)和LD算法

    一. Levenshtein 距离 许多基因算法(如Wagner-Fischer 算法)基于以下观察计算编辑距离:如果我们构造一个矩阵来保存第一个字符串和第二个字符串的所有前缀,以及所有前缀之间的编辑 ...

  2. AR模型参数估计、Y-W方程、L-D算法原理部分

    实验:AR模型参数估计 一.实验目的 二.实验内容 三.实验原理及方法 3.1 AR模型 3.1.1 AR模型参数估计 3.1.2 AR模型参数和自相关函数的关系 3.2 Y-W方程的解法--L-D算 ...

  3. 编辑距离算法(LD)详解

    编辑距离算法,是自然语言处理中的重要的算法之一.也是从多个相似的字符串组中提取字符串的有利的武器.编辑距离算法,也称为LD算法.LD算法就是自然语言处理(NLP)里的"编辑距离"算 ...

  4. Levenshtein Distance (LD算法) 编辑距离算法原理

    莱文斯坦距离,又称Levenshtein距离,是编辑距离的一种.指两个字串之间,由一个转成另一个所需的最少编辑操作次数.允许的编辑操作包括:将一个字符替换成另一个字符,插入一个字符,删除一个字符. L ...

  5. 算法总结---最常用的五大算法(算法题思路)

    算法总结---最常用的五大算法(算法题思路) 一.总结 一句话总结: [明确所求:dijkstra是求点到点的距离,辅助数组就是源点到目标点的数组] [最简实例分析:比如思考dijkstra:假设先只 ...

  6. 生成树的概念,最小生成树Prim算法 Kruskal算法

    求解最小生成树可以用Prim算法 Kruskal算法

  7. 期望最大化算法(Expectation-Maximum,简称EM)算法+EM算法+EM的应用

    期望最大化算法(Expectation-Maximum,简称EM)算法+EM算法+EM的应用 EM的应用 EM算法有很多的应用,最广泛的就是GMM混合高斯模型.聚类.HMM等等.具体可以参考Jerry ...

  8. 数据结构与算法:算法简介

    数据结构与算法:算法简介 雪柯 大工生物信息 提笔为写给奋进之人 已关注 你说呢 . shenwei356 等 70 人赞同了该文章 引用自算法图解,作者[美] Aditya Bhargava 译袁国 ...

  9. 社团发现算法-BGLL算法(附代码实现)

    一.社团发现算法 人们发现许多实际网络均具有社团结构, 即整个网络由若干个社团组成,社团之间的连接相对稀疏.社团内部的连接相对稠密.社团发现则是利用图拓扑结构中所蕴藏的信息从复杂网络 中解析出其模块化 ...

最新文章

  1. 到底是先更新数据库还是先更新缓存?
  2. Oracle怎么查外键建在哪个表上
  3. Maven 概要介绍
  4. python比c语言好学吗-C 和 Python语言先学哪个好?
  5. 后退到的页面为什么没有执行js_为什么中层没有执行力?
  6. mysql的replace()函数介绍【mysql函数】
  7. IIS设置Access-Control-Allow-Origin
  8. python中的ix是啥_详谈Pandas中iloc和loc以及ix的区别
  9. 初入c++ (八) c++输入和输出
  10. layui移动端适配_web前端-移动端适配方案
  11. 送给初学.net兄弟们的一些话
  12. 华为p20:拍美景,听讲解,旅行更智能
  13. kite插件~快速提高代码速度
  14. 用python简单代码做一个计算器
  15. 阿拉丁指数丨《2021 年度小程序互联网发展白皮书》4.5 亿+DAU 小程序的 6 大发展趋势
  16. 将win10家庭版、教育版系统激活为win10专业版
  17. 小程序 图片显示模式详解
  18. 电源输出端串入IN4007,测量正负电压,压降只有0.3v,为什么不是0.7v左右呢?
  19. win7休眠设置在哪里_电脑休眠好不好,在哪里开启?
  20. [ahk]热键呼叫QQ经常聊天的人

热门文章

  1. 找出汉字的拼音,既有各汉字的首字母和所有汉字的全拼
  2. 易语言多线程多参数自定义封装
  3. 微信公众号“链接”与“超链接”知识大全
  4. 十.OpenCv 特征点检测和匹配
  5. 图像匹配中的特征点检测之斑点检测(一)
  6. Python爬虫拓展应用:最新版本问卷星自动刷,包括解决智能验证、滑块等问题
  7. 二维离散小波变换及其在MATLAB数字图像处理中的应用
  8. IntelliJ IDEA代码缩略图插件CodeGlance
  9. 洛谷 P1078 文化之旅
  10. 超高频RFID服装供应链管理系统