定义:
编辑距离是指将一个字符串转变成另一个字符串所需要的最小编辑数。
问题分析:
(1)分析最优解的结构特征
假设有两个序列分别是Xi={x1,x2,,x3,...xi}和Yj={y1,y2,y3,...,yj},无论这两个序列怎么进行对齐,其有侧只可能有如下3中对齐方式:
- 删除操作 x1,x2,x3,...,xi-1 xi
y1,y2,y3,...,yj - dp[i][j]=dp[i-1][j]+1;
- 插入操作 x1,x2,x3,...,xi -
y1,y2,y3,...,yj-1 yj dp[i][j]=dp[i][j-1]+1;
- 替换操作 x1,x2,x3,...,xi-1 xi
y1,y2,y3,...,yj-1 yj dp[i][j]=dp[i-1][j-1]+diff(i,j)
diff(i,j)是xi到xj的代价,如果xi=yj ,diff(i,j)=0,如果xi!=yj,diff(i,j)=1;
(2)最优值递归式
dp[i][j]表示xi和yj的编辑距离,则dp[i][j]取以上三种情况的最小值。即:
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+diff(i,j));
(3)图解:
以str1="FAMILY",str2="FRAME"为例
先对dp[][]数组进行初始化 先看第一行,i=1,j=1,F=F,diff(1,1)=0;最小为0
DP F R A M E 0 1 2 3 4 5 F 1 A 2 M 3 I 4 L 5 Y 6
F R A M E 0 1 2 3 4 5 F 1 0 A 2 M 3 I 4 L 5 Y 6
diff(1,2)=1; diff(1,3)=1;
F R A M E 0 1 2 3 4 5 F 1 0 1 A 2 M 3 I 4 L 5 Y 6
F R A M E 0 1 2 3 4 5 F 1 0 1 2 A M I L Y
diff(1,4)=1; diff(1,5)=1;
F R A M E 0 1 2 3 4 5 F 1 0 1 2 3 A 2 M 3 I 4 L 5 Y 6
F R A M E 0 1 2 3 4 5 F 1 0 1 2 3 4 A M I L Y
最终dp[][]数组
F R A M E 0 1 2 3 4 5 F 1 0 1 2 3 4 A 2 1 1 1 2 3 M 3 2 2 2 1 2 I 4 3 3 3 2 2 L 5 4 4 4 3 3 Y 6 5 5 5 4 4 (4) 代码:
#include<cstdio> #include<cstring> #include<iostream> #define N 110 using namespace std; int dp[N][N]; char str1[N],str2[N]; int editdistance(char *str1,char *str2){ int len1=strlen(str1); int len2=strlen(str2); for(int i=0;i<=len1;i++)//初始化 dp[i][0]=i; for(int j=0;j<=len2;j++) dp[0][j]=j; for(int i=1;i<=len1;i++){ for(int j=1;j<=len2;j++){ int diff;//判断str[i]是否等于str[j],相等为0,不等为1. if(str1[i-1]==str2[j-1]) diff=0; else diff=1; int temp=min(dp[i-1][j]+1,dp[i][j-1]+1); dp[i][j]=min(temp,dp[i-1][j-1]+diff);//取三者的最小值 } } return dp[len1][len2]; } int main(){ while(cin>>str1>>str2){ cout<<str1<<"和"<<str2<<"的编辑距离是:"<<editdistance(str1,str2)<<endl; } }
/*
输入:
family
frame
输出:
family和frame的编辑距离是:4
*/