#include <iostream>
using namespace std;
//為了方便,將a和b的長度固定下來,這樣就不用動態建立陣列了
#define M 6
#define N 3
int dp[M][N] = {0};
/**
* 問題描述: 兩個字串如果可以根據新增,刪除,修改一個字串來變成另一個字串,則
* 說這兩個字串距離為1. 現在給出兩個字串,求出他們之間的距離。
* abcehk和bdh的距離。
* 要將一個字串變成另一個,這裡假設將B變換成A,很明顯這個問題有子結構。
* 要求f(m,n),即字串A與字串B的距離:
* 如果a[m] == b[n],那麼這個距離就是其上一個狀態,即f(m-1,n-1)。
* 如果a[m] != b[n],
* 要麼刪除b[n],這個時候問題變成f(m,n-1)
* 要麼為B增加一個和a[m]相同的字元讓其與A的結尾相同,這個時候問題變成f(m,n+1) = f(m-1,n)(因為末尾字元相同,故不考慮)。
* 要麼修改b[n]為a[m],這個時候問題變成求解f(m-1.n-1).
* 這些操作的代價都是1,主要是看子問題的代價,選擇最小的。(DP特徵)
*
* 所以我們定義狀態f(m,n)為長度為m的串A與長度為n的串B之間的距離。
* 然後定義狀態轉移方程為:
* f(m,n) =
* f(m-1,n-1), a[m] == b[n]
* min{f(m-1,n-1),f(m,n-1),f(m-1,n)}+1, a[m]!=b[n]
* 自底向上求解,DP求解矩陣的第一行和第一列很容易初始化.
*/
int min(int x, int y, int z){
if(x<y){
if(x<z) return x;
else return z;
}
else{
if(y<z) return y;
else return z;
}
}
int getDistance(char *a, char *b){
if(a==NULL || b==NULL) return 0;
//初始化兩個字串的長度
int a_len=M,b_len=N;
//初始化第一行和第一列
if(a[0] != b[0]) dp[0][0] = 1;
else dp[0][0] = 0;
for(int i=1;i<b_len;i++){ //第一行
if(a[0] != b[i]) dp[0][i] = dp[0][i-1]+1;
else dp[0][i] = dp[0][i-1];
}
for(int j=1;j<a_len;j++){ //第一列
if(b[0] != a[j]) dp[j][0] = dp[j-1][0]+1;
else dp[j][0] = dp[j-1][0];
}
//開始自底向上計算
for(i=1;i<a_len;i++){
for(j=1;j<b_len;j++){
if(a[i] == b[j]) dp[i][j] = dp[i-1][j-1];
else{
dp[i][j] = min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j])+1;
}
}
}
//列印出最短距離陣列
for(i=0;i<a_len;i++){
for(j=0;j<b_len;j++){
cout<<dp[i][j]<<" ";
}
cout<<endl;
}
return dp[M-1][N-1];
}
int main(){
/**
* 注意順序,這裡a作為列,b作為行
*/
char *a = "abcehk";
char *b = "beh";
cout<<getDistance(a,b)<<endl;
return 0;
}