1. 程式人生 > >動態規劃--編輯距離問題

動態規劃--編輯距離問題

一、問題描述

設A和B是2個字串。要用最少的字元操作將字串A轉換為字串B。這裡所說的字元操作包括 (1)刪除一個字元; (2)插入一個字元; (3)將一個字元改為另一個字元。 將字串A變換為字串B所用的最少字元運算元稱為字串A到 B的編輯距離,記為d(A,B)。 對於給定的字串A和字串B,計算其編輯距離 d(A,B)。

輸入格式:

第一行是字串A,檔案的第二行是字串B。

提示:字串長度不超過2000個字元。

輸出格式:

輸出編輯距離d(A,B)

輸入樣例:

fxpimu
xwrs 

輸出樣例:

 5

二、演算法分析

我們把問題一步步執行,每一步的執行都依賴上一步的決策(刪除、插入、替換),即子問題具有重疊性,同時子問題的求解都有最佳決策,所以這是一個動態規劃問題。這裡定義一個二維陣列d[i][j]儲存操作,表示字串i到字串j的距離。

1)假如i長度大於j進行刪除做作使i變成j, 則此時d[i][j] = d[i - 1][j] + 1;

2)假如i長度小於j進行插入操作,即刪除j末尾元素, 使i與j相等, 則此時d[i][j] = d[i][j - 1] + 1;

3) 假如i長度等於j,則判斷i和j最後一個元素相不相等。若相等則d[i][j] = d[i-1][j-1] + 1.

得出遞迴公式:d[i][j] =min(d[i-1][j-1] + diff(), d[i][j-1]+1, d[i-1][j]+1)

三、程式碼

 

#include <iostream>
#include 
<cstring> using namespace std; int min(int a, int b, int c) { int temp = a < b ? a : b; return temp < c ? temp : c; } int m(string a, string b) { int E[a.length() + 1][b.length() + 1]; // 初始化二維陣列 for (int i = 0; i <= a.length(); i++) { E[i][0] = i; } for
(int i = 0; i <= b.length(); i++) { E[0][i] = i; } //演算法實現 for (int i = 1; i <= a.length(); i++) { for (int j = 1; j <= b.length(); j++) { int diff = (a[i - 1] == b[j - 1] ? 0 : 1);//diff表示相同則加0,不相同加1 E[i][j] = min(E[i - 1][j] + 1, E[i][j - 1] + 1, E[i - 1][j - 1] + diff); } } return E[a.length()][b.length()]; } int main() { string i, j; cin >> i >> j; cout << d(i, j) << endl;

四、時空分析

因為用了一個數組儲存兩層for,所以時間複雜度為O(i*j),空間複雜度為O(i*j)。

五、結對總結

通過互相講述做題過程,從而對題目有了一個更加清晰的認知,也對做題方法起到了很好的總結作用。