当前位置:网站首页>子序列 --- 编辑距离
子序列 --- 编辑距离
2022-07-23 08:03:00 【ATTACH_Fine】
392. 判断子序列
题目
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
示例:
思路
1.确定dp数组(dp table)以及下标的含义
dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。
2.确定递推公式
if (s[i - 1] == t[j - 1]) -----> t中找到了一个字符在s中也出现了—> dp[i][j] = dp[i - 1][j - 1] + 1;
if (s[i - 1] != t[j - 1]) -----> 相当于t要删除元素,继续匹配 -------> dp[i][j] = dp[i][j - 1]
3.初始化
出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]是一定要初始化的。
dp[0][0] = 0;
dp[i][0] 表示以下标i-1为结尾的字符串,与空字符串的相同子序列长度,所以为0.
4. 确定遍历顺序
遍历顺序也应该是从上到下,从左到右
代码
class Solution {
public boolean isSubsequence(String s, String t) {
//dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。
int len1 = s.length();
int len2 = t.length();
int[][] dp = new int[len1+1][len2+1];
//初始化 dp[0][0] 和 dp[i][0] 均为零,不用拿出来单独初始化
for(int i = 1; i <= len1; i++){
for(int j =1; j <= len2; j++){
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = dp[i][j-1];
}
}
}
return dp[len1][len2] == len1;
}
}
115. 不同的子序列
题目
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中t出现的个数。
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,“ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)
示例:
思路
1.确定dp数组(dp table)以及下标的含义
dp[i][j]:以i-1为结尾的s子序列 中 出现以j-1为结尾的t的个数为dp[i][j]。
2.确定递推公式
是要分析两种情况:
s[i - 1] 与 t[j - 1]相等
s[i - 1] 与 t[j - 1] 不相等
当s[i - 1] 与 t[j - 1]相等时,dp[i][j]可以有两部分组成。
一部分是用s[i - 1]来匹配,那么个数为dp[i - 1][j - 1]。
一部分是不用s[i - 1]来匹配,个数为dp[i - 1][j]
(1) 当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
(2) 当s[i - 1] 与 t[j - 1]不相等时,dp[i][j]只有一部分组成,不用s[i - 1]来匹配,即:dp[i - 1][j] dp[i][j] = dp[i - 1][j];
3.初始化
dp[i][0] 和dp[0][j]是一定要初始化的。
dp[i][0] 表示:以i-1为结尾的s可以随便删除元素,出现空字符串的个数。 出现空字符串的个数就是1。
dp[0][j]:空字符串s可以随便删除元素,出现以j-1为结尾的字符串t的个数。dp[0][j]一定都是0
4.确定遍历顺序
一定是从上到下,从左到右
代码
class Solution {
public int numDistinct(String s, String t) {
//dp[i][j]:以i-1为结尾的s子序列 中 出现以j-1为结尾的t的个数为dp[i][j]。
int len1 = s.length();
int len2 = t.length();
int[][] dp = new int[len1+1][len2+1];
//初始化:dp[0][j]始终是0
for(int i = 0; i <= len1; i++){
dp[i][0] = 1;
}
for(int i = 1; i <= len1; i++){
for(int j = 1; j <= len2; j++){
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
}else{
dp[i][j] = dp[i-1][j];
}
}
}
return dp[len1][len2];
}
}
583 两个字符串的删除操作
题目
给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。
每步 可以删除任意一个字符串中的一个字符。
示例:
思路
1.确定dp数组(dp table)以及下标的含义
dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。
2 确定递推公式
(1)当word1[i - 1] 与 word2[j - 1]相同的时候,dp[i][j] = dp[i - 1][j - 1];
(2)当word1[i - 1] 与 word2[j - 1]不相同的时候,有三种情况:
情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1
情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1
情况三:同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2
最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});
3.初始化
dp[i][0] 和 dp[0][j]是一定要初始化的。
dp[i][0]:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。
dp[0][j]的话同理
for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
4.确定遍历顺序
递推公式 dp[i][j] = min(dp[i - 1][j - 1] + 2, min(dp[i - 1][j], dp[i][j - 1]) + 1); 和dp[i][j] = dp[i - 1][j - 1]可以看出dp[i][j]都是根据左上方、正上方、正左方推出来的。
所以遍历的时候一定是从上到下,从左到右,这样保证dp[i][j]可以根据之前计算出来的数值进行计算。
代码
class Solution {
public int minDistance(String word1, String word2) {
//dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。
int len1 = word1.length();
int len2 = word2.length();
int[][] dp = new int[len1+1][len2+1];
//初始化
for(int i = 0; i <= len1; i++){
dp[i][0] = i;
}
for(int j = 0; j <= len2; j++){
dp[0][j] = j;
}
for(int i = 1; i <= len1; i++){
for(int j = 1; j <= len2; j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = Math.min(dp[i-1][j-1]+2,Math.min(dp[i-1][j]+1,dp[i][j-1]+1));
}
}
}
return dp[len1][len2];
}
}
72. 编辑距离
题目
给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
示例:
1.确定dp数组(dp table)以及下标的含义
dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
2. 确定递推公式
if (word1[i - 1] == word2[j - 1])
不操作 -----> dp[i][j] = dp[i - 1][j - 1];
if (word1[i - 1] != word2[j - 1])
增
删
换
if (word1[i - 1] != word2[j - 1])
操作一:删除元素
word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作
dp[i][j] = dp[i - 1][j] + 1
操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作
dp[i][j] = dp[i][j - 1] + 1;
操作二:添加元素
**!!! word2添加一个元素,相当于word1删除一个元素,**例如 word1 = “ad” ,word2 = “a”,word1删除元素’d’ 和 word2添加一个元素’d’,变成word1=“a”, word2=“ad”, 最终的操作数是一样!
操作三:替换元素
word1替换word1[i - 1],使其与word2[j - 1]相同,此时不用增加元素,那么以下标i-2为结尾的word1 与 j-2为结尾的word2的最近编辑距离 加上一个替换元素的操作。同理,word2替换word2[j - 1],使其与word1[i - 1]相同,也是如下式子
即 dp[i][j] = dp[i - 1][j - 1] + 1;
!!!综上,当 if (word1[i - 1] != word2[j - 1]) 时取最小的,即:dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
3.初始化
dp[i][0] 和 dp[0][j]
dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]。
那么dp[i][0]就应该是i,对word1里的元素全部做删除操作,即:dp[i][0] = i; 同理dp[0][j] = j;
4.确定遍历顺序
代码
class Solution {
public int minDistance(String word1, String word2) {
//dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
int len1 = word1.length();
int len2 = word2.length();
int[][] dp = new int[len1+1][len2+1];
//初始化
for(int i = 0; i <= len1; i++){
dp[i][0] = i;
}
for(int j = 0; j <= len2; j++){
dp[0][j] = j;
}
for(int i = 1; i <= len1; i++){
for(int j = 1; j <= len2; j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = Math.min(Math.min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+1);
}
}
}
return dp[len1][len2];
}
}
边栏推荐
猜你喜欢

How about the nuclear display performance of Ruilong R7 Pro 6850h? What level is it equivalent to

mysql开启定时调度任务执行

Comment creo 9.0 modifie - t - il rapidement le système de coordonnées Cao?

Remember that a vulnhub target plane exercise successfully won the root permission

Day 5 experiment

MySQL enables scheduled task execution

Notes on the seventh day

PyTorch到底好用在哪里?

What is Tianji 920 equivalent to a snapdragon? How much is Tianji 920 equivalent to a snapdragon? How about Tianji 920

The difference between rtx3080ti and 3090. Which one is more cost-effective, rtx3080ti or 3090
随机推荐
Notes on the fifth day
天玑920相当于骁龙什么 天玑920相当于骁龙多少 天玑920怎么样
小米12S Pro和小米12Pro天玑版区别 两者配置对比
Which is the difference between iqoo 10 pro and vivo X80 pro? Detailed parameter configuration comparison
机器学习入门难?说说我是如何快速开始机器学习入门的!
第七天笔记
鸡与蛋,产品与策略
【百企行】牛耳教育助力高校访企拓岗促就业专项行动
Is there a big gap between core i5 12490f and i5 12600K
MYSQL练习题:向CEO汇报的所有员工
overlayfs源代码解析
Process blocks and methods
Detailed explanation of knapsack problem
Medium range
OSPF details (1)
设计例化和连接
rtx3080相当于gtx什么显卡 rtx3080显卡什么水平 rtx3080显卡怎么样
Ansible first knowledge of learning one
Surrounded Regions
激励发生器、监测器