1. 程式人生 > >編輯距離

編輯距離

最小值 align 是否 table [] time 替換 字符串 ace

定義:

編輯距離是指將一個字符串轉變成另一個字符串所需要的最小編輯數。

問題分析:

(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
*/

編輯距離