Minimum Edit Distance 问题
解法一:分治
问题:对于不同的字符串,判断其相似度或求二者的“距离”。
定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:
1.修改一个字符(如把“a”替换为“b”)
2.增加一个字符(如把“abdd”变为“aebdd”)
3.删除一个字符(如把“travelling”变为“traveling”)
定义:把这个操作所需要的最少次数定义为两个字符串的距离,而相似度等于“距离+1”的倒数
思想:采用递归的思想将问题转化成规模较小的同样的问题。
分析:
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
2. Computing Minimum Edit Distance
我们定义D(i,j)为 X 的前i个字符 X[1...i] 与 Y 的前j个字符 Y[1...j] 之间的距离,其中0<i<n, 0<j<m,因此X与Y的距离可以用D(n,m)来表示。
3. Backtrace for Computing Alignments
4. Weighted Minimum Edit Distance
5. Minimum Edit Distance in Computational Biology
源代码:
/*
* 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
谨此略作修改。

浙公网安备 33010602011771号