Levenshtein distance最小编辑距离算法实现

47 篇文章 37 订阅
9 篇文章 2 订阅

动态编程| (编辑距离)

给定两个字符串str1和str2以及可以对str1执行的操作。找出将“str1”转换为“str2”所需的最小编辑次数(操作)。

  1. 插入
  2. 删除
  3. 代替

所有上述操作具有相等的成本。

例子:

输入:str1 =“geek”,str2 =“gesek” 
输出:1 
我们可以通过插入一个's'将str1转换为str2。

输入:str1 =“cat”,str2 =“cut” 
输出:1 
我们可以通过将'a'替换为'u'来将str1转换为str2。

输入:str1 =“sunday”,str2 =“saturday” 
输出:3 
最后三个字符和第一个字符相同。我们基本上
需要将“un”转换为“ atur ”。这可以使用
以下三个操作来完成。
将“n”替换为“r”,插入t,插入a

这种情况下的子问题是什么?
这个想法是从两个字符串的左侧或右侧逐个处理所有字符。
让我们从右边角度穿越,对于每一对字符都有两种可能性。

m: str1(第一个字符串)的
 长度n: str2(第二个字符串)的长度
  1. 如果两个字符串的最后字符相同,没有什么可做的。忽略最后一个字符并获取剩余字符串的计数。因此,我们重复长度m-1和n-1。
  2. Else(如果最后字符不相同),我们考虑对“str1”的所有操作,考虑对第一个字符串的最后一个字符的所有三个操作,递归计算所有三个操作的最小成本,并取最少三个值。
    1. 插入:对m和n-1重复
    2. 删除:重复m-1和n
    3. 替换:对m-1和n-1重复

下面是上面Naive递归解的Java实现。

Java

// A Naive recursive Java program to find minimum number
// operations to convert str1 to str2
class EDIST
{
     static int min( int x, int y, int z)
     {
         if (x<y && x<z) return x;
         if (y<x && y<z) return y;
         else return z;
     }
 
     static int editDist(String str1 , String str2 , int m , int n)
     {
         // If first string is empty, the only option is to
     // insert all characters of second string into first
     if (m == 0 ) return n;
      
     // If second string is empty, the only option is to
     // remove all characters of first string
     if (n == 0 ) return m;
      
     // If last characters of two strings are same, nothing
     // much to do. Ignore last characters and get count for
     // remaining strings.
     if (str1.charAt(m- 1 ) == str2.charAt(n- 1 ))
         return editDist(str1, str2, m- 1 , n- 1 );
      
     // If last characters are not same, consider all three
     // operations on last character of first string, recursively
     // compute minimum cost for all three operations and take
     // minimum of three values.
     return 1 + min ( editDist(str1,  str2, m, n- 1 ),    // Insert
                      editDist(str1,  str2, m- 1 , n),   // Remove
                      editDist(str1,  str2, m- 1 , n- 1 ) // Replace                    
                    );
     }
 
     public static void main(String args[])
     {
         String str1 = "sunday" ;
         String str2 = "saturday" ;
  
         System.out.println( editDist( str1 , str2 , str1.length(), str2.length()) );
     }
}
/*This code is contributed by Rajat Mishra*/
在IDE上运行
输出:

3

上述解的时间复杂度是指数的。在最坏的情况下,我们可能最终做O(3 m)操作。最坏的情况发生在两个字符串的字符都不匹配时。下面是最坏情况下的递归调用图。
EditDistance

我们可以看到,许多子问题被一次又一次解决,例如eD(2,2)被称为三次。由于相同的suproblems被再次调用,这个问题具有重叠子属性。因此,编辑距离问题具有动态规划问题的属性(见这个这个)。像其他典型的动态编程(DP)问题一样,通过构造存储子参数结果的临时数组,可以避免重新计算相同的子问题。

  • Java

Java

// A Dynamic Programming based Java program to find minimum
// number operations to convert str1 to str2
class EDIST
{
     static int min( int x, int y, int z)
     {
         if (x < y && x <z) return x;
         if (y < x && y < z) return y;
         else return z;
     }
 
     static int editDistDP(String str1, String str2, int m, int n)
     {
         // Create a table to store results of subproblems
         int dp[][] = new int [m+ 1 ][n+ 1 ];
      
         // Fill d[][] in bottom up manner
         for ( int i= 0 ; i<=m; i++)
         {
             for ( int j= 0 ; j<=n; j++)
             {
                 // If first string is empty, only option is to
                 // isnert all characters of second string
                 if (i== 0 )
                     dp[i][j] = j;  // Min. operations = j
      
                 // If second string is empty, only option is to
                 // remove all characters of second string
                 else if (j== 0 )
                     dp[i][j] = i; // Min. operations = i
      
                 // If last characters are same, ignore last char
                 // and recur for remaining string
                 else if (str1.charAt(i- 1 ) == str2.charAt(j- 1 ))
                     dp[i][j] = dp[i- 1 ][j- 1 ];
      
                 // If last character are different, consider all
                 // possibilities and find minimum
                 else
                     dp[i][j] = 1 + min(dp[i][j- 1 ],  // Insert
                                        dp[i- 1 ][j],  // Remove
                                        dp[i- 1 ][j- 1 ]); // Replace
             }
         }
  
         return dp[m][n];
     }
 
     
 
     public static void main(String args[])
     {
         String str1 = "sunday" ;
         String str2 = "saturday" ;
         System.out.println( editDistDP( str1 , str2 , str1.length(), str2.length()) );
     }
} /*This code is contributed by Rajat Mishra*/
在IDE上运行
spaces”>                                    dp[i - 1 ][j - 1 ])    # Replace
 
     return dp[m][n]
 
# Driver program
str1 = "sunday"
str2 = "saturday"
 
print (editDistDP(str1, str2, len (str1), len (str2)))
# This code is contributed by Bhavya Jain
Run on IDE

输出:

3

时间复杂度:O(m×n)
辅助空间:O(m×n)

应用:有很多实际应用的编辑距离算法,参考Lucene API的样例。另一个例子,显示字典中靠近给定单词\拼写错误的单词的所有单词。

arrPost.push('13178'); arrPost.push('Dynamic Programming | Set 5 (Edit Distance)'); arrPost.push('http://www.geeksforgeeks.org/dynamic-programming-set-5-edit-distance/'); arrPost.push('Dynamic Programming');
3.2 平均难度:3.2 / 5.0
基于162票,






编辑距离算法是一种用来衡量字符串之间相似度的算法,它可以计算出将一个字符串转换为另一个字符串所需的最小操作数。 编辑距离计算使用了Levenshtein distance算法,该算法由俄罗斯数学家Vladimir Levenshtein在1965年提出。它通过插入、删除和替换字符来计算两个字符串之间的距离算法的基本思想是逐个比较字符串中的字符,当字符不相同时,可以选择进行插入、删除或替换操作,使得两个字符相等,从而减小距离。通过一系列的操作,最后可以得到两个字符串相等的情况。 在计算过程中,算法使用了一个二维矩阵来表示两个字符串之间的距离。矩阵的行表示源字符串的字符,列表示目标字符串的字符。矩阵中的每个值表示在当前位置上,通过一系列操作所需的最小距离。通过动态规划的方式,算法逐步填充矩阵,直到计算得到整个矩阵。 计算编辑距离的过程是从左上角到右下角的遍历,每一步都考虑当前位置的字符是否相等,如果相等,则跳过该字符;如果不相等,则可以选择插入、删除或替换操作,并选择最小操作数。最后,右下角的值即为两个字符串之间的编辑距离编辑距离算法可以应用于许多领域,如拼写纠正、基因序列比对等。通过计算字符串之间的相似度,可以帮助我们理解文本、数据的相似性程度,从而提供更好的数据处理与分析效果。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值