Minimum Edit Distance 问题
解法一:
对于不同的字符串,判断其相似度。
定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:
1.修改一个字符(如把“a”替换为“b”)
2.增加一个字符(如把“abdd”变为“aebdd”)
3.删除一个字符(如把“travelling”变为“traveling”)
定义:把这个操作所需要的最少次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数
采用递归的思想将问题转化成规模较小的同样的问题。
u
如果两个串的
第一个字符相同
,如A=xabcdae和B=xfdfa,只要计算
A[2,…,7]=abcdae和B[2,…,5]=fdfa的距离就可以了。
u
如果两个串的
第一个字符不相同
,那么可以进行如下的操作:
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]变成相同字符串。
伪代码
int calculateStringDistance(string strA, int pABegin, int pAEnd, string strB, int pBBegin, int pBEnd)
{
if(pABegin > pAEnd) //递归终止条件
{
if(pBBegin > pBEnd) return 0;
else return pBEnd - pBBegin + 1;
}
if(pBBegin > pBEnd)
{
if(pABegin > pAEnd) return 0;
else return pAEnd - pABegin + 1;
}
if(strA[pABegin] == strB[pBBegin]) //算法核心
{
return calculateStringDistance(strA, pABegin+1, pAEnd, strB, pBBegin+1, pBEnd);
}
else
{
int t1 = calculateStringDistance(strA, pABegin, pAEnd, strB, pBBegin+1, pBEnd);
int t2 = calculateStringDistance(strA, pABegin+1, pAEnd, strB, pBBegin, pBEnd);
int t3 = calculateStringDistance(strA, pABegin+1, pAEnd, strB, pBBegin+1, pBEnd);
return minValue(t1, t2, t3) + 1;
}
}
简洁版
#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;
}
上面的算法有什么地方需要改进呢?
算法中,有些数据被重复计算。
为了避免这种重复计算,我们可以考虑将子问题计算后的解保存起来
动态规划 求解
第一部分讲解:http://blog.csdn.net/huaweidong2011/article/details/7727482
本篇内容将讲述Edit Distance(编辑距离的定义详见正文),具体又包含5个方面的内容:
- Defining Minimum Edit Distance
- Computing Minimum Edit Distance
- Backtrace for Computing Alignments
- Weighted Minimum Edit Distance
- Minimum Edit Distance in Computational Biololgy
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算法。
第二部分 代码:http://blog.csdn.net/abcjennifer/article/details/7735272
自然语言处理(NLP)中,有一个基本问题就是求两个字符串的minimal Edit Distance, 也称Levenshtein distance。受到一篇Edit Distance介绍文章的启发,本文用动态规划求取了两个字符串之间的minimal Edit Distance. 动态规划方程将在下文进行讲解。
1. what is minimal edit distance?
简单地说,就是仅通过插入(insert)、删除(delete)和替换(substitute)个操作将一个字符串s1变换到另一个字符串s2的最少步骤数。熟悉算法的同学很容易知道这是个动态规划问题。
其实一个替换操作可以相当于一个delete+一个insert,所以我们将权值定义如下:
I (insert):1
D (delete):1
S (substitute):2
2. example:
intention->execution
Minimal edit distance:
delete i ; n->e ; t->e ; insert c ; n->u 求和得cost=8
3.calculate minimal edit distance dynamically
思路见注释,这里D[i,j]就是取s1前i个character和s2前j个character所得minimal edit distance
三个操作动态进行更新:
D(i,j)=min { D(i-1, j) +1, D(i, j-1) +1 , D(i-1, j-1) + s1[i]==s2[j] ? 0 : 2};中的三项分别对应D,I,S。
/*
* 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
Reference:
1. https://www.coursera.org/course/nlp
2. http://blog.csdn.net/huaweidong2011/article/details/7727482