字符串編輯距離
字符串編輯距離
字符串的編輯距離,又稱為Levenshtein距離,由俄羅斯的數學家Vladimir Levenshtein在1965年提出。是指利用字符操作,把字符串A轉換成字符串B所需要的最少操作數。其中,字符操作包括:
- 刪除一個字符
- 插入一個字符
- 修改一個字符
例如對於字符串"if"和"iff",可以通過插入一個‘f‘或者刪除一個‘f‘來達到目的。
問題描述:給定兩個字符串A和B,求字符串A至少經過多少步字符操作變成字符串B。
我們先以一個例子分析,比如eat變成tea。對於第一個字符,e != a,所以要想讓這兩個字符相等,有三種可以選擇的辦法
- 修改字符,將e直接變成a,需要走1步。
- 插入字符,在e的前面插入a,也需要走1步。
- 刪除字符,將e刪除,然後比較後面的與a,也需要走1步。
如果是 e==a,那麽就可以直接跳過這個字符比較下面的字符,那麽他們的距離也就是前面一步的舉例了。
經過舉例子分析,很容易發現這是一個動態規劃問題,那麽我們就按照動態規劃的一套方法來求解。
1、維護一個dp數組,其中dp[i][j]表示s1[0]---s1[i]和s2[0]--s2[j]相同需要進行的最少步驟;
2、邊界條件初始化,dp[i][0]=i,相當於將s1挨個變成空所要進行的步數,對於dp[0][j]=j同理;
3、狀態轉移方程,我們要得到dp[i][j]的值,假設s1[i-1]和s2[j-1]之前的都已經相等了,那麽如果s1[i]==s2[j],顯然不需要進行操作,dp[i][j]==dp[i-1][j-1];如果s1[i]!=s2[j],那麽到達dp[i][j]的就有三條路,分別從dp[i-1][j-1]、dp[i-1][j]、dp[i][j-1],對應的含義分別是修改字符、刪除字符和插入字符,在三種操作下,經歷的步數都要+1,所以我們只要找三者的最小值然後+1就可以了。
這個題目有一種巧妙的理解辦法,就是畫表格。畫表格法在動態規劃太有用了!!!特別是處理這種數組是二維的情況,可以直觀的理解狀態轉移的過程,非常值得學習。
這裏以s1="cafe" s2="coffee"。表格如下:
(1)初始狀態,這裏要註意dp數組的長度要比字符串長度+1,因為要保存字符串為空的狀態c | o | f | f | e | e | ||
c | |||||||
a | |||||||
f | |||||||
e |
c | o | f | f | e | e | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
c | 1 | ||||||
a | 2 | ||||||
f | 3 | ||||||
e | 4 |
- 對角數字+1(對於3,4來說為2)
- 左方數字+1(對於3,4格來說為1)
- 上方數字+1(對於3,4格來說為3)
c | o | f | f | e | e | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
c | 1 | 0 | 1 | ||||
a | 2 | ||||||
f | 3 | ||||||
e | 4 |
c | o | f | f | e | e | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
c | 1 | 0 | 1 | 2 | 3 | 4 | 5 |
a | 2 | 1 | 1 | 2 | 3 | 4 | 5 |
f | 3 | 2 | 2 | 1 | 2 | 3 | 4 |
e | 4 | 3 | 3 | 2 | 2 | 2 | 3 |
1 public void mineditdistance(){ 2 String s1 = "cafe"; 3 String s2 = "coffee"; 4 int[][] dp = new int[s1.length()+1][s2.length()+1]; 5 //對dp數組初始化 6 for ( int i = 0 ; i < dp.length ; i ++ ) dp[i][0] = i; 7 for ( int j = 0 ; j < dp[0].length ; j ++ ) dp[0][j] = j; 8 9 for ( int i = 1 ; i < dp.length ; i ++ ){ 10 for ( int j = 1 ; j < dp[0].length; j ++ ){ 11 if ( s1.charAt(i-1) == s2.charAt(j-1) ) dp[i][j] = dp[i-1][j-1]; 12 else dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1; 13 } 14 } 15 System.out.println(dp[dp.length-1][dp[0].length-1]); 16 } 17 public int min(int a, int b, int c){ 18 return Math.min(a,Math.min(b,c)); 19 }
這個是面試時問的問題,在狀態轉移方程地方卡住了。回來好好又分析了一遍,頗有收獲。
字符串+極值 問題,第一個想到的就是用dp把。還有很多類似的問題,後續會慢慢總結。
例題參考:https://blog.csdn.net/ac540101928/article/details/52786435
字符串編輯距離