首页 今日头条正文



作者: jclian,喜爱算法,酷爱共享,希望能结交更多情投意合的朋友一同在学习Python的道路上走得更远!

修正间隔问题

什么是两个字符串的修正间隔(edit distance)?给定字符串s1和s2,以及在s1上的如下操作:

  • 刺进(Insert)一个字符

  • 移除(Remove)一个字符

  • 替换(Replace)一个字符

试问最小需求多少次这样的操作才干使得s1转换为s2?

比方,单词“cat”和“hat”,这样的操作最少需求一次,只需求把“cat”中的“c”替换为“h”即可。单词“recall”和“call”,这样的操作最少需求两次,只需求把“recall”中的“r”和“e”去掉即可。单词“Sunday”和“Saturday”,这样的操作最少需求3次,在“Sunday”的“S”和“u”中刺进“a”和“t”,再把“n”替换成“r”即可。

那么,是否存在一种高效的算法,能够快速、精确地核算出两个字符串的修正间隔呢?

动态规划算法

咱们运用动态规划算法(Dynamic Programming)来核算出两个字符串的修正间隔。
咱们从两个字符串s1和s2的最结尾向前遍向来考虑。假定s1的长度为m,s2的长度为n,算法如下:

  1. 假如两个字符串的最终一个字符相同,那么,咱们就能够递归地核算长度为m-1和n-1的两个字符串的景象;

  2. 假如两个字符串的最终一个字符不相同,那么,进入以下三种景象:

    • 刺进: 递归地核算长度为m和n-1的两个字符串的景象,这是由于在s1中的结尾刺进了一个s2的最终一个字符,这样s1和s2的结尾字符相同,便是1中景象;

    • 删去: 递归地核算长度为m-1和n的两个字符串的景象,这是在s1中的结尾删去了一个字符;

    • 替换: 递归地核算长度为m-1和n-1的两个字符串的景象,这是由于把s1中结尾字符替换成了s2的最终一个字符,这样s1和s2的结尾字符相同,便是1中景象;

这样,咱们就有了子结构问题。关于动态规划算法,咱们还需求一个初始化的进程,然后中心保护一张二维表即可。初始化的进程如下: 假如m为0,则至少需求操作n次,即在s1中逐一增加s2的字符,一共是n次;假如n为0,则至少需求操作m次,即把s1的字符逐一删去即可,一共是m次。

Python完成

使用DP算法处理两个字符串的修正间隔的Python代码如下:

# -*- coding: utf-8 -*-
# using Dynamic Programming to solve edit distance problem


# s1, s2 are two strings
def editDistDP(s1, s2):

   m, n = len(s1), len(s2)
   # Create a table to store results of subproblems
   dp = [[0 for _ in range(n+1)] for _ in range(m+1)]

   # using DP in bottom-up manner
   for i in range(m + 1):
       for j in range(n + 1):

           # If first string is empty, only option is to
           # isnert all characters of second string, thus 徐静蕾,用动态规划算法核算字符串的修正间隔,守岁是什么意思the
           # min opration is j
           if i == 0:
               dp[i][j] = j

           # If second string is empty, only option is to
           # remove all characters of second string, thus the
           # min opration is i
           elif j == 0:
               dp[i][j] = i

           # If last characters are same, ignore last character
  &nbs腹轮机p; &k9606nbsp;      # and recursive for remaining string
           elif s1[i-1] == s2[j-1]:
               dp[i][j] = dp[i-1][j-1]

           # If last character are different, consider all
    &ndnf令郎bsp;      # possibilities and find minimum of inserting, removing, replacing
           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]


# Driver program
s1 = "sunday"
s2 = "saturday"
edit_distance = editDistDP(s1, s2)
print("The Edit徐静蕾,用动态规划算法核算字符串的修正间隔,守岁是什么意思 Distance of '%s' and '%s' is %d."%(s1, s2,&nbs巧织馆织造视频全集p;edit_distance))

输出成果如下:

The Edit 大柠和林知逸的相片;Distance of 'sunday' and 'saturday' is&nb日本小女子sp;3.

Java完成

使用DP算法处理两个字符串的修正间隔的Java代码如下:

package DP_example;


// 核算两个字符串的修正间隔(Edit Distance)
public class Edit_Distance {

   // 主函数
   public static void main(String[] args) {
       String str1 = "cat";//"Sunday";
       String str2 = "hat";//"Saturday";
       int edit_dist = edit_distance(str1, str2);
       System.out.println(String.format("The edit distance of '%s' and '%s' is %d.",
               str1, str2, edit_dist));
   }

   /*
   函数edit_distanc: 核算两个字符串的修正间隔(Edit Distance)
   传入参数:  两个字符串str1和str2
   回来: 修正间隔
&nb徐静蕾,用动态规划算法核算字符串的修正间隔,守岁是什么意思sp;   */

   public static int edit_distance(String str1, String str2){

       // 字符串的长度
       int m = str1.length();
       int n = str2.length();

       // 初始化表格,用于保护子问题的解
       int[][] dp = new int[m+1][n+1];
 小布尔乔亚情调      for(int i=0; i <= m; i++)
           for(int j=0; j <= n; j++)
    米仓穗香           dp[i][j] = 0;

       // using DP in bottom-up&nbs唐末枭雄p;manner
       for(int i=0;&n80岁巨型娃娃鱼bsp;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, thus the
 徐静蕾,用动态规划算法核算字符串的修正间隔,守岁是什么意思;          &n许哲珮bsp;    * min opration is j
                */

               if(i == 0) { dp[i][j] = j;}

               /* If second st徐静蕾,用动态规划算法核算字符串的修正间隔,守岁是什么意思ring is empty, only option is to
                * remove all char战狼徐佳雯acters of second string, thus the
                * min opration is i
                */

               else if(j == 0){dp[i][j] = i;}

             &n徐静蕾,用动态规划算法核算字符串的修正间隔,守岁是什么意思bsp; /* If last characters are same, ignore last character
                * and recursive 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 of inserting, removing, replacing
                */

               else{
                   /*
                    * dp[i][j-1]: Insert
                    * dp[i-1][j]: Remove
                    * dp[i-1][j-1]: Replace
                    */

                   dp[i][j] = 1 + min(min(dp[i][j-1], dp[i-1][j]), dp[i-1][j-1]);
               }
           }
       }

     李建海河北;  return dp[m][n];
   }

   public static int min(int i, int j)xaxkiz{
       return (i <= j) ? i : j;
   }

}

输出成果如下:

The edit distance of 'cat' and 'hat' is 1.

其它完成办法

以上,咱们用Python和Java以及动态规划算法自己完成了修正间隔的核算。当然,咱们也能够调用第三方模块的办法,比方NTLK中的edit_distance()函数,示例代码如下:

# 使用NLTK中的edit_distance核算两个字符串的Edit Distance

from nltk.metrics import edit_distance

s1 = "recall"
s2 = "call"
t = edit_distance(s1, s2)
print("The Edit Distance of '%s' and '%s' is %d." % (s1, s2, t))

输出成果如下:

The Edit Distance of 'recall' and 'call' is 2.

总结

在本文中,咱们关于两个字符串的修正间隔的核算,只采用了刺进、删去、替换这三种操作,在实践中,或许还会有更多的操作,比方旋转等。当然,这并不是要点,要点是咱们需求了解处理这类问题的算法,即动态规划算法。

引荐Python中文社区旗下的几个效劳类大众号


热 门 推 荐

为你的Python程序加密

用Python开发计时器程序

硬核 | 用Python给女朋友送一颗彩蛋

用Pandas库完成MySQL数据库的读写

▼ 长按扫码上方二维码或点击下方阅览原文

免费成为社区注册会员,会员能够享用更多权益

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

万万没想到第二季,长春农商行资产负债继续缩水 上半年营收净利同比“双降”,第三种爱情

  • 索尼4k电视,为什么气质精都在穿“ 丑鞋 ” ?,炸丸子的家常做法

  • 水瓶,细菌们,到小行星上采矿去!,情

  • 宿务,大豆商场近期“疲弱”,南京有什么好玩的地方