代码随想录算法训练营Day56 | 583. 两个字符串的删除操作 | 72. 编辑距离 | 编辑距离总结篇

文章目录

  • 583. 两个字符串的删除操作
    • 抽象化:最长公共子序列的长度
    • dp 记录删除元素的数量
  • 72. 编辑距离
  • 编辑距离总结篇

583. 两个字符串的删除操作

题目链接 | 解题思路

本题的第一反应应该是进行最长公共子序列的抽象化,因为删除元素这个操作看上去很复杂。但实际上,也能通过 dp 来记录删除操作,也为后面那道编辑距离打下了基础。

抽象化:最长公共子序列的长度

从两个不同的字符串删除元素直到相同,也可以理解为找到最长公共子序列之后就删除多余的元素。这样的抽象化后,可以直接套用找最长公共子序列的解法,在最后用两个字符串的总长度减去两倍的最长公共子序列长度即可。

class Solution:def minDistance(self, word1: str, word2: str) -> int:dp = [[0] * len(word2) for _ in range(len(word1))]first_row_flag = first_col_flag = Falsefor j in range(len(word2)):if word1[0] == word2[j]:first_row_flag = Trueif first_row_flag:dp[0][j] = 1for i in range(len(word1)):if word1[i] == word2[0]:first_col_flag = Trueif first_col_flag:dp[i][0] = 1for i in range(1, len(word1)):for j in range(1, len(word2)):if word1[i] == word2[j]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = max(dp[i-1][j], dp[i][j-1])return len(word1) + len(word2) - 2 * dp[-1][-1]

dp 记录删除元素的数量

删除元素看着很复杂,因为从结果上来看,删除这个步骤可以发生在任一字符串的任一位置,没办法通过 dp 找到规律。但实际上,只要在 dp 的递推中正确递推了最优解,那就可以解题。

初始化终于变的复杂了,不能再直接初始化第一行和第一列。对于这样的数据,构造对应 "" 的第0行和第0列才是正道!

  1. dp 数组的下标含义:dp[i][j]word1[:i]word2[:j] 能够达到相同需要的最少删除数(这里定义的改变和后面的)
  2. dp 递推公式:
    • 如果 word1[i] == word2[j],那么不需要对这两个尾部元素进行任何删除,dp[i][j] = dp[i-1][j-1]
    • 否则,必然要至少删掉一个元素才能使得有可能使得两个字符串能够匹配,所以 dp[i][j] = min(dp[i-1][j], dp[i][j-1])
      • 注意,当然有可能这两个尾部元素都需要删除,但这个情况 dp[i-1][j-1] + 2 被包含在了 dp[i-1][j], dp[i][j-1] 中,可以不需要额外考虑
  3. dp 的初始化:
    • 对于 word1="" 来说,需要删除 word2[:j] 中所有的元素才行,也就是 dp[0][j] = j
    • 同理,dp[i][0] = i
  4. dp 遍历顺序:从上到下、从左到右即可
  5. 举例推导:word1 = "sea", word2 = "eat"
‘’sea
‘’0123
e1212
a2321
t3432
class Solution:def minDistance(self, word1: str, word2: str) -> int:dp = [[0] * (len(word2) + 1) for _ in range(len(word1) + 1)]for i in range(len(word1) + 1):dp[i][0] = ifor j in range(len(word2) + 1):dp[0][j] = jfor i in range(1, len(word1) + 1):for j in range(1, len(word2) + 1):if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]else:dp[i][j] = min(dp[i][j-1], dp[i-1][j]) + 1return dp[-1][-1]

72. 编辑距离

题目链接 | 解题思路

  1. dp 数组的下标含义:dp[i][j] 是将 word1[:i] 转换成 word2[:j] 的最少操作数(定义和初始化有点关系,类似于背包问题)

  2. dp 递推公式:

    • 如果 word1[i-1] == word2[j-1],那么各自的结尾元素不需要进行任何操作,直接转换成之前的子问题,dp[i][j] = dp[i-1][j-1]
    • 否则,我们显然需要进行一次操作(insert、delete、change)才能转换成之前的子问题
      • 如果需要进行 insert,显然我们是希望在 word1[:i] 的后面加上一个 word2[i-1],这样将当前问题转换成了子问题:“将 word1[:i] 转换成 word2[:j-1]”,dp[i][j] = dp[i][j-1] + 1
      • 如果需要进行 delete,显然我们是希望删除 word1[i-1],这样将当前问题转换成了子问题:“将 word1[:i-1] 转换成 word2[:j]”,dp[i][j] = dp[i-1][j] + 1
      • 如果需要进行 change,显然我们是希望将 word1[i-1] 变成 word2[j-1],这样将当前问题转换成了子问题:“将 word1[:i-1] 转换成 word2[:j-1]”,dp[i][j] = dp[i-1][j-1] + 1
    • 由于我们需要记录最小操作数,所以 dp[i][j] = min([dp[i-1][j-1], dp[i-1][j], dp[i][j-1]]) + 1
  3. dp 数组的初始化:本题如果直接进行第一行和第一列的初始化,难度无疑逆天,所以才用了背包问题一样处理 "" 的定义来帮助初始化

    • 对于 i=0 (word1 = ""),将其转化成 word2[:j] 显然需要 j 次操作(insert),所以 dp[0][j] = j
    • 对于 j=0 (word2 = ""),将 word2[:i] 其转化成 "" 显然需要 i 次操作(delete),所以 dp[i][0] = i
    • 这样的初始化比真正处理长度为 1 的 word1, word2 要正常多了
  4. dp 的遍历顺序:递推依赖左上方的元素,从上到下、从左到右即可

  5. 举例说明:word1 = "horse", word2 = "ros"

    ''ros
    ''0123
    h1123
    o2212
    r3222
    s4332
    e5443
class Solution:def minDistance(self, word1: str, word2: str) -> int:dp = [[0] * (len(word2) + 1) for _ in range(len(word1) + 1)]for i in range(len(word1) + 1):dp[i][0] = ifor j in range(len(word2) + 1):dp[0][j] = jfor i in range(1, len(word1) + 1):for j in range(1, len(word2) + 1):if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]else:dp[i][j] = min([dp[i-1][j-1], dp[i][j-1], dp[i-1][j]]) + 1return dp[-1][-1]

编辑距离总结篇

编辑距离总结

在之前的讲解中,或多或少提到了编辑距离。那些题目或多或少都有一些别的解法,或者看作是重复字数组、重复子序列的变种。但是,实际上他们都能被看作是编辑距离这个终极版本的削弱版本:

  • 判断子序列 可以看作:只允许删除 t 的元素的情况下能否得到 s
  • 不同的子序列 可以看作:有多少种删除 t 的元素的方法能够得到 s
  • 两个字符串的删除操作 可以看作:允许删除两个字符串的元素,使其相同所需要的最少操作数
  • 编辑距离 就是真正的编辑距离

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/77694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Debug C++之opencv下Mat的data赋值问题,出现段错误(核心已转储)

记录一个Mat赋值报错问题: 通常算法对软件的接口没有Mat类型,需要传unsigned char*标定Mat的data,宽度和高度三个信息: 例如,下面的接口定义了两张图像,用于相机对图像处理后的返回结果,接口信息…

亚马逊环境友好承诺标签申请指南-FSC®认证产品篇

【亚马逊环境友好承诺标签申请指南-FSC认证产品篇】 2023年8月2日FSC国际推出自助式服务平台——FSC认证产品门户网站,FSC证书持有者可以通过该平台添加自己的认证产品,并可通过平台加入亚马逊的“环境友好承诺”(Climate Pledge Friendly, 简…

计算机竞赛 推荐系统设计与实现 协同过滤推荐算法

0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 推荐系统设计与实现 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1…

Matplotlib渲染3D模型【Wavefront .OBJ】

推荐:用 NSDT编辑器 快速搭建可编程3D场景 Matplotlib 有一个非常漂亮的 3D 界面,具有许多功能(和一些限制),在用户中非常受欢迎。 然而,对于某些用户(或者可能对于大多数用户)来说&…

基于Android 语音朗读书籍管理系统

视频演示: 基于Android 语音朗读书籍管理系统 基于 Android 的语音朗读书籍管理系统可以提供用户管理书籍、朗读书籍的功能。以下是一个简单的步骤和功能列表: 用户注册和登录功能: 用户可以注册新账号或使用现有账号登录系统。用户信息可以包…

软件自动化测试有哪些步骤?自动化测试需要找第三方检测机构吗?

您是否曾经因为软件出现问题而影响了工作进程或者个人生活的正常运转?那么,您是否了解软件自动化测试这一神奇的技术?在这篇文章中,我们将为您介绍软件自动化测试的定义和测试步骤,帮助您更好地了解自动化测试。 一、什么是软件自动化测试…

预约微信小程序源码系统制作搭建 适用于多场景 支持万能DIY功能

分享一个预约微信小程序源码系统,适用于多种预约场景,含完整代码包前端后端详细的搭建教程,支持万能DIY功能,让你轻松开发制作一个属于自己的想要的预约小程序。 一、预约微信小程序源码系统制作搭建的基本步骤和注意事项&#xf…

第5篇 vue的通信框架axios和ui框架-element-ui以及node.js

一 axios的使用 1.1 介绍以及作用 axios是独立于vue的一个项目,基于promise用于浏览器和node.js的http客户端。 在浏览器中可以帮助我们完成 ajax请求的发送在node.js中可以向远程接口发送请求 1.2 案例使用axios实现前后端数据交互 1.后端代码 2.前端代码 &…

拿走吧你,Fiddler模拟请求发送和修改响应数据

模拟伪造请求 方法一:打断点模拟HTTP请求 1、浏览器页面填好内容后(不要操作提交),打开fiddler,设置请求前断点,点击菜单fiddler,”Rules”\”Automatic Breakpoints”\”Before Requests” 2、在页面上点…

构建本地yum仓库

此操作针对VMware虚拟机安装的centos系统,yum本地仓库构建仅作参考。 1、挂载光盘 [rootwww ~]# umount /dev/cdrom 【推出原来挂载的光盘】 umount: /dev/cdrom: not mounted [rootwww ~]# mkdir /media/cdrom [rootwww ~]# mount /dev/cdrom /media/cdrom/ 【挂载…

前端每日小计

1.依赖检查depcheck 项目package.json中依赖确实,可用depcheck检查 进入项目根目录运行depcheck,查看Missing dependecies 2.文件名大小写调整后,git无变化,设置core.ignorecasefase 添加git config core.ignorecase false配置 3.…

Java面试题总结2023

Java面试题总结2023 基础String中常用的方法 与 equals的区别值传递和引用传递数组和集合的区别成员变量和局部变量的区别final和finally和finalize的区别Cookie和Session的的区别接口分类接口和抽象类的区别说说你对抽象类的理解String/StringBuffer/StringBuilderjdk1.8的新特…

批量复制文件到指定文件夹,智能跳过相同文件名!

大家好!在进行文件管理的过程中,如果需要将大量文件快速复制到指定文件夹,并避免重复文件名带来的混乱,传统的手动操作可能会非常繁琐和耗时。为了让您能够高效地完成这一任务,我们为您提供了一种智能方法,…

SpringMVC之综合案例:参数传递,向页面传参,页面跳转

参数传递向页面传参页面跳转 1.参数传递 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"htt…

Android 通用首页代码示例

在 Android 中&#xff0c;使用 NestedScrollView 来包含多个部分&#xff0c;如横向 Banner、GridView 和 RecyclerView&#xff0c;可以通过嵌套不同的布局组件来实现。以下是一个示例布局的 XML 文件&#xff0c;展示如何将这些部分嵌套在 NestedScrollView 内&#xff1a; …

长胜证券:三大拐点共振 看好智能驾驶新一轮行情

摘要 【长胜证券&#xff1a;三大拐点共振 看好智能驾驭新一轮行情】长胜证券研报指出&#xff0c;全球共振&#xff0c;国内智驾商场正迎来三大拐点&#xff1a;1&#xff09;技能上&#xff0c;“BEV Transformer数据闭环”新架构2023年开端上车&#xff0c;使得不依靠高精地…

HONEYWELL 0574-A-012 0574-A-0131 编码器模块

HONEYWELL 0574-A-012 0574-A-0131 编码器模块是一种用于测量旋转或线性位置的设备&#xff0c;通常用于自动化系统、机器控制和传感器应用。以下是HONEYWELL 0574-A-012 0574-A-0131 编码器模块可能具备的一些常见产品特点&#xff1a; 高精度测量&#xff1a;HONEYWELL 0574-…

Linux学习之MySQL备份

xtrabackup资源下载 完全备份与恢复 # 1.物理备份与恢复 # 冷备份&#xff0c;需停止数据库服务 适合线下服务器。 [rootmysql50 ~]# systemctl stop mysqld [rootmysql50 ~]# mkdir /bakdir [rootmysql50 ~]# cp -r /var/lib/mysql /bakdir/mysql.bak [rootmysql50 ~]# cd /…

Linux编译器-gcc/g++使用

文章目录 前言一、gcc/g编译器1、gcc/g安装2、gcc介绍3、gcc和g区别3.1 gcc不是只能编译.c源文件3.2 gcc和g编译文件3.3 gcc 不会定义 __cplusplus 宏&#xff0c;而 g 会3.5 演示 4、gcc/g编译过程 二、动态库和静态库1、动态库和静态库2、动态链接和静态链接2.1 动态链接2.2 …

STL stack 和 queue

文章目录 一、stack 类和 queue 类的模拟实现 stack 只允许在一端进行插入删除&#xff0c;是一个后进先出(LIFO)的结构&#xff0c;可以存储任意类型 queue 只允许在一端进行插入&#xff0c;另一端进行删除&#xff0c;是一个先进先出(FIFO)的结构&#xff0c;可以存储任意类…