首頁 Java java教程 字串的編輯距離實例詳解

字串的編輯距離實例詳解

Jun 30, 2017 am 09:34 AM
動態規劃 字串 距離

  動態規劃的演算法題往往都是各大公司筆試題的常客。在不少演算法類的微信公眾號中,關於「動態規劃」的文章屢見不鮮,都在試圖用最淺顯易懂的文字來描述講解動態規劃,甚至有的用漫畫來解釋,認真讀每一篇公眾號推送的文章其實都能讀懂,都能對動態規劃有個大概了解。

  什麼是動態規劃?通俗地理解來說,一個問題的解決辦法一看就知道(窮舉),但不能一個一個數啊,你得找到最優的解決辦法,換句話說題目中就會出現類似“最多”、“最少”,“一共有多少種”等提法,這些題理論上都能使用動態規劃的思想來求解。 動態規劃與分治方法類似,都是透過組合子問題的解來求解原問題,但它對每個子問題只求解一次,將其保存在表格中,無需重新計算,通常用於求解最最佳化問題——《演算法導論》#。

  編輯距離(Edit Distance),本文指的是Levenshtein距離,也就是字串S1透過插入、修改、刪除三種運算最少能轉換成字串S2#的次數。例如:S1 = abcS2 = abf,編輯距離d = 1#(只需將c修改為f)。在本文中將利用動態規劃的演算法思想對字串的編輯距離求解。

  定義:S1、S2表示兩個字串S1(i)表示S 1的第一個字元d[i, j]表示#S1i個前綴到S2的第j個前綴(例如:S1 = ” abc”,S2 = ”def”,求解S1#S2的編輯距離d[ 3, 3])。

  1.   若S1 = ”abc”, S2 = ”dec”,此時它們的編輯距離為d[3, 3] = 2 ,觀察兩個字串的最後一個字元是相同的,也就是說S1(3) = S2(3)不需要做任何變換,故S1 = ”abc”, S2 = ”dec” <= > S1' = ”ab”, S2' = ”de”,即當S1[i] = S[j]d [i, j] = d[i-1,j -1]。得到公式:d[i, j] = d[i - 1, j - 1] (S1[i] = S2[j])

  2.   上面一條得出了當S1[i] = S2[j]的計算公式,顯然還有另一個情況就是S1[i] ≠ S2[j],若S1 = ”abc”, S2 = ”def”。 S1變換到S2的過程可以修改##」,但也可以透過插入##刪除#”使得S1#變換為#S2

  3.     1)在
S1

字串末位插入字元「f」,此時S1 = ”abcf”,S2 = ”def”,此時即S1[i] = S2[j]的情況S1變換為S2的編輯距離為##d[4, 3] = d[ 3, 2]。所以得出d[i, j]=d[i, j - 1] + 1。 (+1是因為S1新增了」f」    2 )在S2

字串末位元插入字元“c”,此時S1 = ”abc” S2 = ”defc”#,此時即S1[i] = S[j]#的情況,S1變換為S2的編輯距離為#d[3, 4] = d[2, 3] 。所以得出d[i, j]=d[i - 1, j] + 1,實際上這是對S1做了 刪除。 (+1是因為S2新增了」c”    3 )將S1

字串末位元字元修改”f”##S1 = ”abf”S2 = ”def”#,此時即#S1[i] = S[j] 的情況,S1變換為S2的編輯距離為d[3, 3] = d[2, 2]。所以得出d[i, j] = d[i – 1, j - 1] + 1。 (+1是因為S1修改了“c”##)  綜上,得出遞推公式:

=>

#  不妨用表格表示動態規劃對S1=”abc”S2=“def”的求解過程。

  可以看出紅色方塊即是最終所求的編輯距離,整個求解過程就是填滿這個表— —二維數組。以下是JavaPython分別對字串編輯距離的動態規劃求解。

  Java

  1 package com.algorithm.dynamicprogramming;  2   3 
  /**  4  * 动态规划——字符串的编辑距离  5  * s1 = "abc", s2 = "def"  6  
  * 计算公式:  7  *          | 0                                          
   i = 0, j = 0  8  *          | j                                          
    i = 0, j > 0  9  * d[i,j] = | i                                          
     i > 0, j = 0 10  *          | min(d[i,j-1]+1, d[i-1,j]+1, d[i-1,j-1])    s1(i) = s2(j) 11  
     *          | min(d[i,j-1]+1, d[i-1,j]+1, d[i-1,j-1]+1)  s1(i) ≠ s2(j) 12  * 定义二维数组[4][4]: 13 
      *      d e f            d e f 14  *   |x|x|x|x|        |0|1|2|3| 15  
      * a |x|x|x|x|  =>  a |1|1|2|3|  => 编辑距离d = [3][3] = 3 16  * b |x|x|x|x|      
      b |2|2|2|3| 17  * c |x|x|x|x|      c |3|3|3|3| 18  * 19  * Created by yulinfeng on 6/29/17. 20  
      */ 21 public class Levenshtein { 22  23     public static void main(String[] args) { 24         
      String s1 = "abc"; 25         String s2 = "def"; 26         int editDistance = levenshtein(s1, s2); 27         
      System.out.println("s1=" + s1 + "与s2=" + s2 + "的编辑距离为:" + editDistance); 28     } 29  30     /** 31      
      * 编辑距离求解 32      * @param s1 字符串s1 33      * @param s2 字符串s2 34      * @return 编辑距离 35      
      */ 36     private static int levenshtein(String s1, String s2) { 37         int i = 0;  //s1字符串中的字符下标 38      
         int j = 0;  //s2字符串中的字符下标 39         char s1i = 0;   //s1字符串第i个字符 40         
         char s2j = 0;   //s2字符串第j个字符 41         int m = s1.length();    //s1字符串长度 42         
         int n = s2.length();    //s2字符串长度 43         if (m == 0) {   
         //s1字符串长度为0,此时的编辑距离就是s2字符串长度 44             return n; 45         } 46         
         if (n == 0) { 47             return m;   //s2字符串长度为0,此时的编辑距离就是s1字符串长度 48         }          
         int[][] solutionMatrix = new int[m + 1][n + 1];     //求解矩阵 50         
         /** 51          *      
         d e f 52         *   |0|x|x|x| 53         
          * a |1|x|x|x| 54         
           * b |2|x|x|x| 55          
         * c |3|x|x|x| 56    */ 57         for (i = 0; i < m + 1; i++) { 58             solutionMatrix[i][0] = i; 59         } 60         
         /** 61          *      d e f 62         
          *   |0|1|2|3| 63          
          * a |x|x|x|x| 64          
          * b |x|x|x|x| 65          
         * c |x|x|x|x| 66          */ 67         for (j = 0; j < n + 1; j++) { 68             solutionMatrix[0][j] = j; 69         } 70         
         /** 71          * 上面两个操作后,求解矩阵变为 72         
          *      d e f 73         
           *   |0|1|2|3| 74          
         * a |1|x|x|x| 75         
          * b |2|x|x|x| 76         
          * c |3|x|x|x| 77          
          * 接下来就是填充剩余表格 78          
         */ 79         for (i = 1; i < m + 1; i++) {   //i = 1,j = 1, 2, 3,以行开始填充 80             s1i = s1.charAt(i - 1); 81             
         for (j = 1; j < n + 1; j++) { 82                 s2j = s2.charAt(j - 1); 83                 int flag = (s1i == s2j) ? 0 : 1;    
         //根据公式,如果s1[i] = s2[j],则d[i,j]=d[i-1,j-1],如果s1[i] ≠ s2[j],则其中一个公式为d[i,j]=d[i-1,j-1]+1 84                 
         solutionMatrix[i][j] = min(solutionMatrix[i][j-1] + 1, solutionMatrix[i-1][j] + 1, solutionMatrix[i-1][j-1] + flag); 85             
         } 86         } 87         return solutionMatrix[m][n]; 88     } 89  90     /** 91      * 根据公式求解编辑距离 92      
         * @param insert s1插入操作 93      * @param delete s1删除操作 94      * @param edit s1修改操作 95      * @return 编辑距离 96      
         */ 97     private static int min(int insert, int delete, int edit) { 98         int tmp = insert < delete ? insert : delete; 99         
         return tmp < edit ? tmp : edit;100     }101 }
登入後複製

  Python3

 1 &#39;&#39;&#39; 2     动态规划——字符串的编辑距离 3     s1 = "abc", s2 = "def" 4     
 计算公式: 5              | 0                                          
  i = 0, j = 0 6              | j                                           
  i = 0, j > 0 7     d[i,j] = | i                                          
   i > 0, j = 0 8              | min(d[i,j-1]+1, d[i-1,j]+1, d[i-1,j-1])    s1(i) = s2(j) 9              
   | min(d[i,j-1]+1, d[i-1,j]+1, d[i-1,j-1]+1)  s1(i) ≠ s2(j)10     
   定义二维数组[4][4]:11         d e f            d e f12     |x|x|x|x|        
   |0|1|2|3|13     a |x|x|x|x|  =>  a |1|1|2|3|  => 编辑距离d = [4][4] = 314     b |x|x|x|x|      
   b |2|2|2|3|15     c |x|x|x|x|      c |3|3|3|3|16 '''17 def levenshtein(s1, s2):18     i = 0  
    #s1字符串中的字符下标19     j = 0   #s2字符串中的字符下标20     s1i = ""    #s1字符串第i个字符21     
    s2j = ""    #s2字符串第j个字符22     m = len(s1) #s1字符串长度23     n = len(s2) #s2字符串长度24    
     if m == 0:25         return n    #s1字符串长度为0,此时的编辑距离就是s2字符串长度26     if n == 0:27        
      return m    #s2字符串长度为0,此时的编辑距离就是s1字符串长度28     
      solutionMatrix = [[0 for col in range(n + 1)] for row in range(m + 1)]  #长为m+1,宽为n+1的矩阵29     '''30       
      d e f31           |0|x|x|x|32         a |1|x|x|x|33         b |2|x|x|x|34        
       c |3|x|x|x|35     '''36     for i in range(m + 1):37         solutionMatrix[i][0] = i38     '''39       
      d e f40           |0|1|2|3|41         a |x|x|x|x|42         b |x|x|x|x|43         
       c |x|x|x|x|44         45     '''46     for j in range(n + 1):47         solutionMatrix[0][j] = j48     '''49         
       上面两个操作后,求解矩阵变为50              d e f51           |0|1|2|3|52         a |1|x|x|x|53        
        b |2|x|x|x|54         c |3|x|x|x|55         接下来就是填充剩余表格56     '''57     for x in range(1, m + 1):58         
        s1i = s1[x - 1]59         for y in range(1, n + 1):60             s2j = s2[y - 1]61             flag = 0 if s1i == s2j  else 162             
        solutionMatrix[x][y] = min(solutionMatrix[x][y-1] + 1, solutionMatrix[x-1][y] + 1, solutionMatrix[x-1][y-1] + flag)63 64     
        return solutionMatrix[m][n]65 66 def min(insert, delete, edit):67     tmp = insert if insert < delete else delete68     
        return tmp if tmp < edit else edit69 70 s1 = "abc"71 s2 = "def"72 distance = levenshtein(s1, s2)73 print(distance)
登入後複製

 

##

以上是字串的編輯距離實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Golang字串是否以指定字元結尾的判斷方法 Golang字串是否以指定字元結尾的判斷方法 Mar 12, 2024 pm 04:48 PM

標題:Golang中判斷字串是否以指定字元結尾的方法在Go語言中,有時候我們需要判斷一個字串是否以特定的字元結尾,這在處理字串時十分常見。本文將介紹如何使用Go語言來實現這項功能,同時提供程式碼範例供大家參考。首先,讓我們來看看Golang中如何判斷一個字串是否以指定字元結尾的方法。 Golang中的字串可以透過索引來取得其中的字符,而字串的長度可

怎麼重複字串_python重複字串教程 怎麼重複字串_python重複字串教程 Apr 02, 2024 pm 03:58 PM

1.先開啟pycharm,進入到pycharm首頁。 2.然後新建python腳本,右鍵--點選new--點選pythonfile。 3.輸入一段字串,代碼:s="-"。 4.接著需要把字串裡面的符號重複20次,代碼:s1=s*20。5、輸入列印輸出代碼,代碼:print(s1)。 6.最後運行腳本,在最底部會看到我們的回傳值:-就重複了20次。

PHP中int型別轉字串的方法詳解 PHP中int型別轉字串的方法詳解 Mar 26, 2024 am 11:45 AM

PHP中int型別轉字串的方法詳解在PHP開發中,常會遇到將int型別轉換為字串型別的需求。這種轉換可以透過多種方式實現,本文將詳細介紹幾種常用的方法,並附帶具體的程式碼範例來幫助讀者更好地理解。一、使用PHP內建函數strval()PHP提供了一個內建函數strval(),可以將不同類型的變數轉換為字串類型。當我們需要將int型別轉換為字串型別時,

如何在Go語言中截取字串 如何在Go語言中截取字串 Mar 13, 2024 am 08:33 AM

Go語言是一種強大且靈活的程式語言,它提供了豐富的字串處理功能,包括字串截取。在Go語言中,我們可以使用切片(slice)來截取字串。接下來,將詳細介紹如何在Go語言中截取字串,並附上具體的程式碼範例。一、使用切片截取字串在Go語言中,可以使用切片表達式來截取字串的一部分。切片表達式的語法如下:slice:=str[start:end]其中,s

解決PHP中16進位轉字串出現中文亂碼的方法 解決PHP中16進位轉字串出現中文亂碼的方法 Mar 04, 2024 am 09:36 AM

解決PHP中16進位轉字串出現中文亂碼的方法在PHP程式設計中,有時候我們會遇到需要將16進位表示的字串轉換為正常的中文字元的情況。然而,在進行這個轉換的過程中,有時會遇到中文亂碼的問題。這篇文章將為您提供解決PHP中16進位轉字串出現中文亂碼的方法,並給出具體的程式碼範例。使用hex2bin()函數進行16進位轉換PHP內建的hex2bin()函數可以將1

Golang中如何檢查字串是否以特定字元開頭? Golang中如何檢查字串是否以特定字元開頭? Mar 12, 2024 pm 09:42 PM

Golang中如何檢查字串是否以特定字元開頭?在使用Golang程式設計時,經常會遇到需要檢查一個字串是否以特定字元開頭的情況。針對這項需求,我們可以使用Golang中的strings套件所提供的函數來實現。接下來將詳細介紹如何使用Golang檢查字串是否以特定字元開頭,並附上具體的程式碼範例。在Golang中,我們可以使用strings套件中的HasPrefix

PHP字串比對技巧:避免模糊包含表達式 PHP字串比對技巧:避免模糊包含表達式 Feb 29, 2024 am 08:06 AM

PHP字串比對技巧:避免模糊包含表達式在PHP開發中,字串比對是常見的任務,通常用於尋找特定的文字內容或驗證輸入的格式。然而,有時候我們需要避免使用模糊的包含表達式來確保匹配的準確性。本文將介紹一些在PHP中進行字串匹配時避免模糊包含表達式的技巧,並提供具體的程式碼範例。使用preg_match()函數進行精確比對在PHP中,可以使用preg_mat

PHP字串操作:去除多餘逗號,保留唯一逗號實作技巧 PHP字串操作:去除多餘逗號,保留唯一逗號實作技巧 Mar 28, 2024 pm 03:02 PM

PHP字串操作:去除多餘逗號,保留唯一逗號實作技巧在PHP開發中,字串處理是一個非常常見的需求。有時候我們需要對字串進行處理,去除多餘的逗號,保留唯一的逗號。在這篇文章中,我將介紹一種實作技巧,並提供具體的程式碼範例。首先,我們來看一個常見的需求:假設我們有一個包含多個逗號的字串,我們需要去除多餘的逗號,只保留唯一的逗號。例如,將"apple,ba

See all articles