1. 程式人生 > >動態規劃之編輯距離:用最少的字元操作將A變換成B

動態規劃之編輯距離:用最少的字元操作將A變換成B

一、問題描述

                設A和B是兩個字串,長度分別為n,m要用最少的字元操作(包括字元的插入、刪除、修改),這樣的操作稱為字串A到B的操作距離,記為d(A,B)。

二、思路分析

                把求解編輯距離分為字串A從0個字元逐漸增加到全部字元分別要變成字串B該如何變化的問題。具體來說就是,首先選用str1來儲存字串A,str2來儲存字串B,distance矩陣來進行具體的運算。考慮到最簡單的情況,str1的長度為0,str2長度不為0;str1長度不為0,str2長度為0,對前一種情況的編輯距離就是m,後一種則是n。為什麼?因為str1為0的時候要麼對str1進行新增,即新增m位的str2,要麼對str2進行m個刪除操作;str2為0的時候,要麼對str1進行n個刪除操作,要麼對str2進行n個新增操作。接下來我們著重考慮一般情況,distance矩陣為[n][m],假定我們從distance[0][0]開始一直操作到了distance[i][j]位置,其中刪除操作肯定是str1比str2長,插入操作str1比str2短,我們所要做的是對distance[i-1][j] 、distance[i][j-1]、distance[i-1][j-1]存的數進行比較,其中最小的就是當前str1和str2的編輯距離。

三、實現過程

               這裡,我們把矩陣抽象出來,

distance矩陣
abc a b c
abe 0 1 2 3
a 1 A處0 D1 G 2
b 2 B處1 E0 H  1
e 3 C處2 F1  I  1
               在A處,由於兩個a相同,左上角為0,為左上角的0+0;B處,左邊加1後得到3,上邊加1後為1,二者不相等,這時要為左上角加1,得到2,取三者中的最小值,為1,以下內容類推,最終結果為I的值。

四、程式碼實現

#include<iostream>
using namespace std;
#define MAX 100

//求三者中的最小值
int minval(int a,int b,int c){
	int zhi=min(a,b);
	int minvalue=min(zhi,c);
	return minvalue;
}
//求二者中的最小值
int min(int a,int b){
	return(a>b?b:a);
}
//編輯距離函式,str1 str2為操作的字串
void editDistance(char *str1,char *str2){
	int lenthofstr1=strlen(str1);
	int lenthofstr2=strlen(str2);
	int distance[MAX][MAX];
        //變數用來遍歷、初始化字串
	int i,j;

	for(i=0;i<lenthofstr1;i++){
		distance[i][0]=i;
	}
	for(i=0;i<lenthofstr2;i++){
		distance[0][i]=i;
	}

	for(i=1;i<lenthofstr1;i++){
		for(j=1;j<lenthofstr2;j++){
                        //如果對應的字元相等,原問題交給子問題處理,即不用任何操作
                        if(str1[i]==str2[j]){
			   distance[i][j]=distance[i-1][j-1];
			}
			else{
                                //否則的話,對左、右、左上角的值進行求最小值
                           distance[i][j]=minval(distance[i-1][j]+1,distance[i][j-1]+1,distance[i-1][j-1]+1);
			}
			cout<<distance[i][j]<<" ";
		}
		cout<<endl;
	}
	cout<<"最少的操作次數是:"<<distance[lenthofstr1-1][lenthofstr2-1];
	
}



int main(){
	char str1[]={"abc"};
	char str2[]={"dabc"};
	editDistance(str1,str2);
	return 0;

}
五、結果顯示