• 编辑距离


    给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

      你可以对一个单词进行如下三种操作:

      插入一个字符
      删除一个字符
      替换一个字符

    代码实现:

     1 # 编辑距离
     2 class Solution:
     3     def minDistance(self, word1: str, word2: str) -> int:
     4         m = len(word2)
     5         n = len(word1)
     6         mem = [[0 for col in range(m + 1)] for row in range(n + 1)]
     7         for i in range(n + 1):
     8             mem[i][0] = i
     9         mem[0] = [i for i in range(m+1)]
    10         for row in range(1, n+1):
    11             for col in range(1, m+1):
    12                 if word1[row-1] == word2[col-1]:
    13                     mem[row][col] = 1 + min(mem[row-1][col], mem[row][col-1],mem[row-1][col-1]-1)
    14                 else:
    15                     mem[row][col] = 1 + min(mem[row-1][col], mem[row][col-1],mem[row-1][col-1])
    16         return mem[-1][-1]

      算法原理:

      

       蓝色边界:列为word1子序列转换为空所需要的操作次数;行为空序列转换为word2的子序列需要的次数;

      计算步骤:

      

      

      

      

      算法思想:

      红色部分注意,min函数里面最后一项减去了1;为什么要这样操作呢?这是因为在等式的右边第一项就是1,而这个1表示不管min函数取到什么都要进行一次操作:当取到mem[i-1,j]表示要删除word1中新加入的字符mem[i-1,j]已经可以将子序列转化为word2的目标子序列;当取mem[i,j-1]时,则为插入一个word2新加入子序列的字符;当取mem[i-1,j-1]时,可以将word1加入的元素替换为word2加入的元素。三种情况都是一步操作得到mem[i,j],但是我们应该注意到两个单词新加入的字符不会影响删除和插入操作,对替换却有很大的影响,若两个字符相同,我们根本不需要替换操作,所以当两个字符相同时,mem[i-1,j-1]要先减去1,因为在前面为了形式统一已经加过1了。

    动态规划的解法

     1 # 基于动态规划的解法
     2 def edit_dist(str1, str2):
     3     
     4     # m,n分别字符串str1和str2的长度
     5     m, n = len(str1), len(str2)
     6     
     7     # 构建二位数组来存储子问题(sub-problem)的答案 
     8     dp = [[0 for x in range(n+1)] for x in range(m+1)] 
     9       
    10     # 利用动态规划算法,填充数组
    11     for i in range(m+1): 
    12         for j in range(n+1): 
    13   
    14             # 假设第一个字符串为空,则转换的代价为j (j次的插入)
    15             if i == 0: 
    16                 dp[i][j] = j    
    17               
    18             # 同样的,假设第二个字符串为空,则转换的代价为i (i次的插入)
    19             elif j == 0:
    20                 dp[i][j] = i
    21             
    22             # 如果最后一个字符相等,就不会产生代价
    23             elif str1[i-1] == str2[j-1]: 
    24                 dp[i][j] = dp[i-1][j-1] 
    25   
    26             # 如果最后一个字符不一样,则考虑多种可能性,并且选择其中最小的值
    27             else: 
    28                 dp[i][j] = 1 + min(dp[i][j-1],        # Insert 
    29                                    dp[i-1][j],        # Remove 
    30                                    dp[i-1][j-1])      # Replace 
    31   
    32     return dp[m][n]
  • 相关阅读:
    QTableView表格控件区域选择-自绘选择区域
    Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格
    QRowTable表格控件(三)-效率优化之-合理使用QStandardItem
    QRowTable表格控件(二)-红涨绿跌
    QRowTable表格控件-支持hover整行、checked整行、指定列排序等
    Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等
    Asp.net MVC利用Ajax.BeginForm实现bootstrap模态框弹出,并进行前段验证
    Bootstrap:弹出框和提示框效果以及代码展示
    Bootstrap treeview增加或者删除节点
    bootstrap-treeview 如何实现全选父节点下所有子节点及反选
  • 原文地址:https://www.cnblogs.com/dan-baishucaizi/p/11890399.html
Copyright © 2020-2023  润新知