演算法:編輯距離問題(動態規劃,詳細解答)
一、問題描述:
設A和B是2個字串,要用最少的字元操作將字串A轉化為字串B。這裡所說的字元操作包括:(1)刪除一個字元;(2)插入一個字元;(3)將一個字元改為另一個字元。將字串A變換為B所用的最少字元運算元稱為字串A到B的編輯距離,記為d(A,B)。試設計一個有效演算法,對任給的2個字串A和B,計算出它們的編輯距離d(A,B)。
示例:
輸入:
fxpimu
xwrs
輸出:
5
二、思路分析:
解法一:直接利用求解最長公共子序列的演算法求出最長公共子序列的長度,然後使用較長字串的長度減去最長公共子序列的長度就是所需的最短步驟。
求解最長公共子序列的演算法的詳解解答見之前的部落格文章,這是連結:https://blog.csdn.net/weixin_46013401/article/details/109329667
解法二:利用二維陣列distance記錄求解的過程,利用其下標表示指向不同字串的元素。
當兩個字元元素相等時,distance[i][j] = distance[i-1][j-1];
當兩個字元元素不相等時,分為三種情況,選取其中所需步驟最少的一個:
第一種:修改其中一個字串的元素,使得雙方待比較的元素都減一。
distance[i][j] = distance[i-1][j-1]+1;
第二種:刪除第一個字串的元素或者新增第二個字串的元素,使之相等
distance[i][j] = distance[i-1][j]+1;
第三種:刪除第二個字串的元素或者新增第一個字串的元素,使之相等
distance[i][j] = distance[i][j-1]+1;
for(int i = 1;i<=m;i++)
for(int j = 1;j<=n;j++) {
if(x[i]==y[j]) //兩個字串對應的元素相等
distance[i][j] = distance[i-1][j-1];
else//不相等時分為三種操作型別,選擇其中所需步驟最小的情況!(和後一行程式碼操作順序是一一對應的)
//第一種:修改其中一個字串的元素,使得雙方待比較的元素都減一
//第二種:刪除第一個字串的元素或者新增第二個字串的元素,使之相等
//第三種:刪除第二個字串的元素或者新增第一個字串的元素,使之相等
distance[i][j] = minOfThree(distance[i-1][j-1], distance[i-1][j], distance[i][j-1])+1;
}
最終在distance[m][n]處獲得最終結果。
三、程式碼求解:
解法一:
import java.util.Scanner;
public class demo{
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("請輸入第一個字串:");
String str1 = s.nextLine();
System.out.println("請輸入第二個字串:");
String str2 = s.nextLine();
//str1 to str2
int m = str1.length();//第一個字串的長度
int n = str2.length();//第二個字串的長度
int[][] c = new int[m+1][n+1];
//用於記錄其求解過程
int[][] b = new int[m+1][n+1];
//用於記錄其求解路徑
char[] x,y;//統一下標,便於求解
x = new char[m+1];
y = new char[n+1];
for(int i = 1;i<=m;i++)
x[i] = str1.charAt(i-1);
for(int j = 1;j<=n;j++)
y[j] = str2.charAt(j-1);
//呼叫函式進行求解
maxLength(m, n, x, y, c, b);
maxAnswer(m, n, x, b);
int max = m>n?m:n;
System.out.println("需要的步數為:"+(max-count)+"steps");
}
public static void maxLength(int m,int n,char[]x,char[]y,int[][]c,int[][]b) {
//對於陣列c進行初始化
for(int i = 0;i<=m;i++)
c[i][0] = 0;
for(int j = 0;j<=n;j++)
c[0][j] = 0;
for(int i = 1;i<=m;i++)
for(int j = 1;j<=n;j++) {
if(charEqual(x[i], y[j])) {
c[i][j] = c[i-1][j-1]+1;//取對角,兩個字串都減一
b[i][j] = 1;
}else if(c[i-1][j]>=c[i][j-1]) {//取更大的值,說明解更優
c[i][j] = c[i-1][j];//取上面的
b[i][j] = 2;
}else {//取左邊的
c[i][j] = c[i][j-1];
b[i][j] = 3;
}
}
}
//用於比較兩個字元常量是否相等
public static boolean charEqual(char a,char b) {
Character A = new Character(a);
Character B = new Character(b);
if(A.equals(B))
return true;
return false;
}
public static int count = 0;//計數
//用於輸出結果
public static void maxAnswer(int i,int j,char[] x,int[][]b) {
if(i==0||j==0)
return;
//相當於對求解過程思路的原路回溯求解
if(b[i][j]==1) {
maxAnswer(i-1, j-1, x, b);//右上角
count++;
}else if(b[i][j]==2) {
maxAnswer(i-1, j, x, b);//上面
}else {
maxAnswer(i, j-1, x, b);//左邊
}
}
}
解法二:
import java.util.Scanner;
public class demo{
public static void main(String[] args) {
String str1,str2;//用於接受輸入的字串
Scanner s = new Scanner(System.in);
System.out.println("請輸入第一個字串:");
str1 = s.nextLine();
System.out.println("請輸入第二個字串:");
str2 = s.nextLine();
int m = str1.length();//length
int n = str2.length();
char[] x = new char[m+1];//統一下標,便於後續操作
for(int i = 1;i<=m;i++)
x[i] = str1.charAt(i-1);
char[]y = new char[n+1];
for(int j = 1;j<=n;j++)
y[j] = str2.charAt(j-1);
System.out.println("最少需要"+minSteps(m, n, x, y)+"steps");
}
public static int minSteps(int m,int n,char[] x,char[] y) {
int [][]distance = new int[m+1][n+1];
//初始化,當轉換的字串一方為空時,轉換步數為另一方的字串長度
for(int i = 1;i<=m;i++)
distance[i][0] = i;
for(int j = 1;j<=n;j++)
distance[0][j] = j;
for(int i = 1;i<=m;i++)
for(int j = 1;j<=n;j++) {
if(x[i]==y[j]) //兩個字串對應的元素相等
distance[i][j] = distance[i-1][j-1];
else//不相等時分為三種操作型別,選擇其中所需步驟最小的情況!(和後一行程式碼操作順序是一一對應的)
//第一種:修改其中一個字串的元素,使得雙方待比較的元素都減一
//第二種:刪除第一個字串的元素或者新增第二個字串的元素,使之相等
//第三種:刪除第二個字串的元素或者新增第一個字串的元素,使之相等
distance[i][j] = minOfThree(distance[i-1][j-1], distance[i-1][j], distance[i][j-1])+1;
}
return distance[m][n];
}
public static int minOfThree(int x,int y,int z) {
int flag = x<y?x:y;
return (flag<z?flag:z);
}
}
四、執行結果:
五、分析:
時間複雜度 | 空間複雜度 | |
解法一 | O(m*n) | O(m*n) |
解法二 | O(m*n) | O(m*n) |
相關文章
- 動態規劃-編輯距離動態規劃
- Leetcode 編輯距離(動態規劃)LeetCode動態規劃
- 【演算法】動態規劃-優化編輯器問題演算法動態規劃優化
- 編輯距離及編輯距離演算法演算法
- 怎樣衡量兩個字串的相似度(編輯距離動態規劃求解)字串動態規劃
- Hetao P2071 打字遊戲 題解 [ 綠 ] [ 最小生成樹 ] [ 動態規劃 ] [ 編輯距離 ]遊戲動態規劃
- 編輯距離演算法演算法
- 【DP】編輯距離
- 資料對齊-編輯距離演算法詳解(Levenshtein distance)演算法
- 最小總和問題(動態規劃演算法)動態規劃演算法
- 01揹包問題理解動態規劃演算法動態規劃演算法
- 【動態規劃】揹包問題動態規劃
- 揹包問題----動態規劃動態規劃
- 動態規劃之子序列問題動態規劃
- 揹包問題演算法全解析:動態規劃和貪心演算法詳解演算法動態規劃
- LeetCode72編輯距離LeetCode
- 線性dp:編輯距離
- 902.最短編輯距離
- 面試程式碼題(華為)編輯距離面試
- 動態規劃之 KMP 演算法詳解動態規劃KMP演算法
- 找零問題與動態規劃動態規劃
- 醜數問題——動態規劃、Java動態規劃Java
- 動態規劃 01揹包問題動態規劃
- 【動態規劃】01揹包問題動態規劃
- 動態規劃--01揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 動態規劃-01揹包問題動態規劃
- 動態規劃之股票問題123動態規劃
- 動態規劃,股票問題留坑動態規劃
- 詳解動態規劃01揹包問題--JavaScript實現動態規劃JavaScript
- 詳解動態規劃01揹包問題–JavaScript實現動態規劃JavaScript
- 動態規劃之 0-1 揹包問題詳解動態規劃
- Java LeetCode 72. 編輯距離JavaLeetCode
- Leetcode 題解演算法之動態規劃LeetCode演算法動態規劃
- 演算法-動態規劃演算法動態規劃
- 演算法_動態規劃演算法動態規劃
- 動態規劃演算法動態規劃演算法
- 【動態規劃】01揹包問題【續】動態規劃