Minimum Edit Distance 问题

解法一:分治

问题:对于不同的字符串,判断其相似度或求二者的“距离”。

     定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:

   1.修改一个字符(如把“a”替换为“b”)

   2.增加一个字符(如把“abdd”变为“aebdd”)

   3.删除一个字符(如把“travelling”变为“traveling”)

定义:把这个操作所需要的最少次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数

思想:采用递归的思想将问题转化成规模较小的同样的问题。

分析

  如果两个串的第一个字符相同,如A=xabcdae和B=xfdfa,只要计算A[2,…,7]=abcdae和B[2,…,5]=fdfa的距离就可以了。
  如果两个串的第一个字符不相同,那么可以进行如下的操作:
    1.删除A串的第一个字符,然后计算A[2,…,lenA]和B[1,…,lenB]的距离。

    2.删除B串的第一个字符,然后计算A[1,…,lenA]和B[2,…,lenB]的距离。

    3.修改A串的第一个字符为B串的第一个字符,然后计算 A[2,…,lenA] 和 B[2,…,lenB] 的距离。

    4.修改B串的第一个字符为A串的第一个字符,然后计算 A[2,…,lenA] 和 B[2,…,lenB] 的距离。

    5.增加B串的第一个字符到A串的第一个字符之前,然后计算 A[1,…,lenA] 和 B[2,…,lenB] 的距离。

    6.增加A串的第一个字符到B串的第一个字符之前,然后计算 A[2,…,lenA] 和 B[1,…,lenB] 的距离。

  

  我们并不在乎两个字符串变得相等之后的字符串是怎样的。可以将上面6个操作合并为:

    1.一步操作之后,再将A[2,…,lenA]和B[1,…,lenB]变成相同字符串。

    2.一步操作之后,再将A[1,…,lenA]和B[2,…,lenB]变成相同字符串。

    3.一步操作之后,再将A[2,…,lenA]和B[2,…,lenB]变成相同字符串。

伪代码:

 1 int calculateStringDistance(string strA, int pABegin, int pAEnd, string strB, int pBBegin, int pBEnd)
 2 
 3 {
 4  if(pABegin > pAEnd)                                 //递归终止条件
 5  {
 6   if(pBBegin > pBEnd)     return 0;
 7  else  return pBEnd - pBBegin + 1;
 8  }
 9 
10  if(pBBegin > pBEnd)
11 {
12   if(pABegin > pAEnd)   return 0;
13  else  return pAEnd - pABegin + 1;
14 }
15 
16     if(strA[pABegin] == strB[pBBegin])           //算法核心
17 
18    {
19   return calculateStringDistance(strA, pABegin+1, pAEnd, strB, pBBegin+1, pBEnd);
20  }
21 else
22  {
23    int t1 = calculateStringDistance(strA, pABegin, pAEnd, strB, pBBegin+1, pBEnd);
24    int t2 = calculateStringDistance(strA, pABegin+1, pAEnd, strB, pBBegin, pBEnd);
25    int t3 = calculateStringDistance(strA, pABegin+1, pAEnd, strB, pBBegin+1, pBEnd);
26    return minValue(t1, t2, t3) + 1;
27  }
28 
29  } 

简洁版:

#define MAX 100
char s1[MAX];
char s2[MAX];

int distance(char *s1,char *s2)     //求字符串距离
{   int len1=strlen(s1);
    int len2=strlen(s2); 

    if(len1==0||len2==0) 
    { 
       return max(len1,len2); 
     }

      if(s1[0]==s2[0])      return distance(s1+1,s2+1);
      else    return min(distance(s1,s2+1),distance(s1+1,s2),distance(s1+1,s2+1))+1;
}

 

质疑:上面的算法有什么地方需要改进呢?

   算法中,有些数据被重复计算。

  为了避免这种重复计算,我们可以考虑将子问题计算后的解保存起来

 

 

解法二:动态规划 

 

1. Definition of  Minimum Edit Distance 

Edit Distance用于衡量两个strings之间的相似性。
两个strings之间的Minimum edit distance是指把其中一个string通过编辑(包括插入,删除,替换操作)转换为另一个string的最小操作数。

 

 

如上图所示,d(deletion)代表删除操作,s(substitution)代表替换操作,i(insertion)代表插入操作。
(为了简单起见,后面的Edit Distance 简写为ED)
如果每种操作的cost(成本)为1,那么ED = 5.
如果s操作的cost为2(即所谓的Levenshtein Distance),ED = 8.

  

2. Computing Minimum Edit Distance 

  那么如何找到两个strings的minimun edit distance呢?要知道把一个string转换为另一个string可以有很多种方法(或者说“路径“)。我们所知道起始状态(第一个string)、终止状态(另一个string)、基本操作(插入、删除、替换),要求的是最短路径。

 

  对于如下两个strings:
    X的长度为n, Y的长度为m

  我们定义D(i,j)为 X 的前i个字符 X[1...i] 与 Y 的前j个字符 Y[1...j] 之间的距离,其中0<i<n, 0<j<m,因此X与Y的距离可以用D(n,m)来表示。

 

  假如我们想要计算最终的D(n,m),那么可以从头开始,先计算D(i, j) (i和j从1开始)的值,然后基于前面的结果计算更大的D(i, j),直到最终求得D(n,m)。

 

算法过程如下图所示:

 

上图中使用的是”Levenshtein Distance“即替换的成本为2.

 

请读者深入理解一下上图中的循环体部分: D(i,j)可能的取值为:
  1. D(i-1, j) +1 ;
  2. D(i, j-1) +1 ;
  3. D(i-1, j-1) + 2 (当X新增加的字符和Y新增加的字符不同时,需要替换)或者 + 0(即两个字符串新增加的字符相同)

 

下图即对字符串 INTENTION 和 EXECUTION 一步步求ED形成的表。左上角画红圈的8就是两个字符串间的最小ED。

 

 

3. Backtrace for Computing Alignments

  完成以上步骤后,我们求得了Edit distance,但是仅有Edit distance也是是不够的,有时我们也需要把两个strings中的每个字符都一一对应起来(有的字母会与“空白”对应),这可以通过Backtrace(追踪)ED的计算过程得到。
  通过上一节我们知道,D(i, j)的取值来源有三种,D(i-1, j)、D(i, j-1)或者D(i-1, j-1),下表通过添加箭头的方式显而易见地给出来整个表格的计算过程(下面的阴影表示的只是一种路径,你会发现得到最后结果的路径不是惟一的,因为每个单元格数字可能由左边、下边或者左下边的得到)。

 

  从表格右上角开始,沿着追踪的剪头,就可以拎出一条路径出来(不惟一),这条路径的剪头可以轻易的展现是通过哪种方法(插入、删除、替换)完成的。

 

  表格右上角阴影部分四个格子,路径只有一条,我们也可以很轻易地看出最后四个字母是相同的,但这种情况并不绝对,比如中间的阴影6格也只有一种路径,可是却分别对应于字母e和c。

 

  算法实现“寻找路径”的思想很简单——就是给每个单元格定义一个指针,指针的值为LEFT/DOWN/DIAG(不明白为什么他为什么说是指针),如下图所示。

 

 

 
想一下普通的情况,如下图,从(0,0)到(M,N)的任何一条非下降路径都对应于两个strings间的一个排列,而最佳的排列由最佳的子排列组成。

 

简单思考一下算法的性能
  Time:      O(nm)
  Space:     O(nm)
  Backtrace: O(n+m)

 

 
 

 

4. Weighted Minimum Edit Distance

 

  ED也可以添加权重,因为在拼写中,某些字母更容易写错。如下图显示的混淆矩阵,数值越大就代表被误写的可能性越高。如a就很可能被误写为e,i,o,u

 

众所周知,键盘排布会对误写产生影响。
 
Weighted Min Edit Distance的算法如下图所示

 

 

这幅图将del、ins、sub三种操作都定义了不同的权重,在“莱温斯基距离“中,del和ins的cost都是1,sub是2。

 

 

5. Minimum Edit Distance in Computational Biology

 

  本段讲述Minimum Edit Distance在计算生物学中的应用。比如比较如下图(上班部分)两个基因组序列,我们希望最后能把两个序列对齐(下半部分),进而研究不同的基因片段的功能等。

 

 

在Natural Language Processing我们讨论了最小distance和weight,而在Computational Biology中我们将要介绍最大Similarity(相似性)和scores。

 

在Computational Biology中有个重要算法——Needleman-Wunsch算法

 

 

 源代码

/*
 * minEditDis.cpp
 *
 *  @Created on: Jul 10, 2012
 *      @Author: sophia
 *  @Discription: calculate the minimal edit distance between 2 strings
 *
 *  Method : DP (dynamic programming)
 *  D[i,j]: the minimal edit distance for s1的前i个字符和 s2的前j个字符
 *  DP Formulation: D[i,j]=min(D[i-1,j]+1,D[i,j-1]+1,D[i-1,j-1]+flag);//其中if(s1[i]!=s2[j])则flag=2,else flag=0;
 *
 */

#include"iostream"
#include"stdio.h"
#include"string.h"
using namespace std;

#define N 100
#define INF 100000000
#define min(a,b) a<b?a:b

int dis[N][N];
char s1[N],s2[N];
int n,m;//length of the two string


int main()
{
    int i,j,k;
    while(scanf("%s%s",&s1,&s2)!=EOF)
    {
        n=strlen(s1);m=strlen(s2);
        for(i=0;i<=n+1;i++)
            for(j=0;j<=m+1;j++)
                dis[i][j]=INF;
        dis[0][0]=0;

        for(i=0;i<=n;i++)
            for(j=0;j<=m;j++)
            {
                if(i>0) dis[i][j] = min(dis[i][j],dis[i-1][j]+1); //delete
                if(j>0) dis[i][j] = min(dis[i][j],dis[i][j-1]+1);//insert

                //substitute
                if(i>0&&j>0)
                {
                    if(s1[i-1]!=s2[j-1])
                        dis[i][j] = min(dis[i][j],dis[i-1][j-1]+2);
                    else
                        dis[i][j] = min(dis[i][j],dis[i-1][j-1]);
                }
            }

        printf("min edit distance is: %d\n",dis[n][m]);
    }
    return 0;
}

 

运行结果

 

intention

execution

min edit distance is: 8

abc

acbfbcd

min edit distance is: 4

zrqsophia

aihposqrz

min edit distance is: 16

 

 

原文http://blog.csdn.net/sangni007/article/details/7943321

  谨此略作修改。

 

 

 

 

 

posted @ 2013-05-04 20:36  HanelYuki  阅读(372)  评论(0)    收藏  举报