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

来源:互联网 发布:淘宝卖家一个月不发货 编辑:程序博客网 时间:2024/04/30 23:16

动态编程| (编辑距离)

给定两个字符串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的样例。另一个例子,显示字典中靠近给定单词\拼写错误的单词的所有单词。

动态编程
动态编程

关于Venki

软件工程师

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票,






0 0