两个数组的dp问题--动态规划

news2025/4/16 12:47:04

一)最长公共子序列:

1143. 最长公共子序列 - 力扣(LeetCode)

一)定义一个状态表示:根据经验+题目要求

1)选取第一个字符串[0,i]区间以及第二个字符串[0,j]区间作为研究对象,先选取两段区间研究问题,先求出[0,i]中所有的子序列和[0,j]中所有的子序列,然后求出两个子序列中相同的最大的哪一个,找到最长公共子序列的长度;

2)根据题目要求来确定一个状态表示

dp[i][j]就表示s1字符串的[0,i]区间以及s2的[0,j]区间内的所有子序列中(可以包含包含以i,j为结尾,也可以不包含i,j),找到其中的最长的公共子序列的长度 

二)根据状态表示推导状态转移方程:根据最后一个位置的状况来进行划分情况去讨论

如果这两个字符串的最后一个位置的字符相等,那么这两个字符串的最长公共子序列,一定是一这两个字符为结尾的,下面是用反证法来进行证明一下:

 

所以就可以根据这个最后一个字符的状态,分类讨论:

1)if(s1[i]==s2[j]) dp[i][j]=dp[i-1][j-1]+1

2)如果这两个字符不相等,那么最长公共子序列一定不是以这两个字符结尾的

s1[0,i]和s2[0,j-1]

s1[0,i-1],s2[0,j]

s1[0,i-1]和s2[0,j-1]

但是仔细分析之后我们发现,第一种情况已经包含了第三种情况,第二种情况也是已经包含了第三种情况,但是我们此时求的是长度,只需要保证不漏就可以了,如果求的是个数,那么这个状态表示就出现问题了

三)初始化:

1)关于字符串的dp问题,空字符串是有研究意义的,子序列是一个空串那么也是一个公共子序列,引入空串的概念,会方便初始化

2)当i==0或者是j==0的时候,也就是当进行研究第一个字符的时候,dp[i-1]和dp[j-1]会越界,在上面和右边多增加一列,这时当i==0的时候,第一个字符串是空,当j==0的时候,第二个字符串是空,此时dp表新增加的列里面的值全部是初始化成0;

3)添加辅助节点的时候,里面的值要保证我们后续进行填表的时候是正确的,还需要注意下标的映射关系,可以不在填表的时候进行处理,而是可以在所有的字符串前面加上一个空串,这样就可以不用计算下标的映射关系了

 

 四)填表顺序+返回值:从上向下填写每一行,每一行填写从左向右dp[m][n]

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
    int m=text1.length();
    int n=text2.length();
    char[] array1=text1.toCharArray();
    char[] array2=text2.toCharArray();
    int[][] dp=new int[m+1][n+1];
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            if(array1[i-1]==array2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
            else  dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
        }
    }
  return dp[m][n];
    }
}

二)不相交的线

求的是最长公共子序列

1035. 不相交的线 - 力扣(LeetCode)

dp[i][j]表示n1里面的[0,i]区间内以及n2里面的[0,j]区间内的所有子序列中,数组最长公共子序列的长度

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int m=nums1.length;
        int n=nums2.length;
        int[][] dp=new int[m+1][n+1];
        for(int i=1;i<=m;i++){
             for(int j=1;j<=n;j++){
                 if(nums1[i-1]==nums2[j-1]){
                     dp[i][j]=dp[i-1][j-1]+1;
                 }else{
                     dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
                 }
            }
        }
    return dp[m][n];
    }
}

 三)不同的子序列

115. 不同的子序列 - 力扣(LeetCode)

一)定义一个状态表示:

两个字符串的dp表示:dp[i][j]表示从[0,i]位置的t子串在s从[0,j]的子序列中出现的个数

dp[i][j]表示s字符串[0,j]区间内的所有子序列中,有多少个t[0,i]区间内的子串,子串是连续的,但是子序列是不连续的

二)根据状态表示推导状态转移方程:

1)我们可以将s从[0,j]这段字符串的子序列分成两类,就是根据最后一个位置的元素进行划分问题,我们目标是在s的子序列中看看有多少个t字符串

首先求出所有子序列,在求出有多少子序列中等于t

2)可以根据s的子序列中的最后一个位置是否包含j来进行划分问题,s的子序列分成两类

2.1)如果s的子序列中,最后一个位置包含s[j],if(array[i]==array[j]) dp[i][j]=dp[i-1][j-1]

2.2)如果s的子序列中,最后一个位置不包含s[j],dp[i][j]=dp[i][j-1]

我们要找的是[0,i]位置的子串在[0,j]区间内的子序列出现的个数

dp[i][j]就是上面两种情况的的总和

三)初始化+填表顺序+返回值:

3.1)因为有可能使用到i-1和j-1的值,那么我们给dp表新增加一行和一列

3.2)我们下标从1位置和1位置开始,也就是从第一个字符开始进行研究问题

3.3)细节问题:

1)引入空串

2)保证里面的值要保证后面的填表的顺序是正确的

3)还需要注意下表的映射关系:不做任何处理只是在进行填写dp表的时候下标统一进行-1即可

或者是加上在原来的字符串里面加上一个空字符即可

4)当i等于0的时候,说明t字符串是一个空串,那么无论此时j的值等于多少,s的子序列中一定是包含一个空串的,那么所有的dp[0][j]=1

5)那么当j等于0的时候,说明s没有任何子序列,s是一个空串,那么除了i等于0的时候

dp[i][0]都等于0,当i==1的时候,dp[i][0]=1

初始化:从上向下填写每一行,每一行从左向右

返回值:dp[m][n]

class Solution {
    public int numDistinct(String s, String t) {
        char[] array1=t.toCharArray();
        char[] array2=s.toCharArray();
        int[][] dp=new int[array1.length+1][array2.length+1];
        for(int i=0;i<=array2.length;i++){
           dp[0][i]=1;
        }
        for(int j=1;j<=array1.length;j++){
            dp[j][0]=0;
        }
    for(int i=1;i<=array1.length;i++){
        for(int j=1;j<=array2.length;j++){
//1.如果以j为结尾的子序列包含j,况且array1[i]==array2[j]
            if(array1[i-1]==array2[j-1]){
                dp[i][j]=dp[i-1][j-1];
            }
//2.如果以j为结尾的子序列不包含j,
             dp[i][j]+=dp[i][j-1];
        }
    }
    System.out.println(Arrays.deepToString(dp));
  return  dp[array1.length][array2.length];
    }
}

四)通配符匹配

44. 通配符匹配 - 力扣(LeetCode)

五)最长公共前缀:

一)定义一个状态表示:dp[i]表示以i位置为结尾的字符串数组的最长公共前缀

二)根据状态表示状态转移方程:

1)根据最近的一步来进行划分问题,如果发现这个字符串所有的i位置的元素都是相等的,那么最长公共前缀就是dp[i-1]+"ch",但是如果出现了abcde和hhhhe这种情况,如果发现以i-1位置为结尾的最长公共公共前缀是空,那么dp[i]也是空,虽然相等但是没有最长公共前缀

2)如果发现各个字符串在i位置的元素不是全部都相等,那么直接返回dp[i-1]的值

class Solution {
    public String longestCommonPrefix(String[] strs) {
        //dp[i]表示以i位置为结尾字符串数组的最长公共前缀
        String minString=strs[0];
        for(String str:strs){
            if(minString.length()>=str.length()) 
              minString=str;
        }
        if(minString.equals("")) return "";
//1.先进行初始化
       String[] dp=new String[minString.length()];
       char ch=strs[0].charAt(0);
       dp[0]=ch+"";
       for(String str:strs){
           if(str.charAt(0)!=ch){
               dp[0]="";
               break;
           }
       }
//2.进行填表
     for(int i=1;i<minString.length();i++){
           ch=minString.charAt(i);
          for(int j=0;j<strs.length;j++){
              if(strs[j].charAt(i)!=ch){
                return dp[i-1];
              }
          }
        if(!dp[i-1].equals("")) dp[i]=dp[i-1]+ch;
        else dp[i]="";
      }
    return dp[minString.length()-1];
    }
}

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

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

相关文章

redis(8):java连接redis

1 Jedis所需要的jar包依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.1.0</version></dependency> 2 Jedis常用操作 2.1 测试连通性 package com.example.demo;import redis.…

手写Spring,理解SpringBean生命周期

按照Spring使用习惯&#xff0c;准备环境 ​ 首先&#xff0c;写一个TigerApplicationContext&#xff0c;模拟Spring的Annotation Application。然后写一个config&#xff0c;接着写一个UserService。 由于Spring需要扫描bean&#xff0c;所以我们得定义一个扫描注解Componen…

【C++】-priority_queue(优先级队列的具体使用和模拟实现)以及仿函数的简单介绍

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

ubuntu 开启 ssh 服务 设置root远程登录

设置root用户密码 sudo passwd root安装ssh服务和vim编辑器 sudo apt -y install openssh-server vim开启ssh服务 sudo vim /etc/ssh/ssh_config去掉 配置文件中 Port 22 的注释后保存退出 设置root用户远程登录 sudo vim /etc/ssh/sshd_config将 PermitRootLogin prohibit-pas…

文章审核之敏感词过滤

技术选型 DFA实现原理 DFA全称为&#xff1a;Deterministic Finite Automaton,即确定有穷自动机。 存储&#xff1a;一次性的把所有的敏感词存储到了多个map中&#xff0c;就是下图表示这种结构 敏感词&#xff1a;冰毒、大麻、大坏蛋 工具类 最下面的main方法是测试用的&a…

vuejs源码之解析器

解析就是将模版解析成AST。 <div id"app"><p>{{num}}</p> </div>比如下面这个代码&#xff0c;然后转成AST之后是这个样子。 它是用javascript对象来描述一个接待您&#xff0c;一个对象表示一个节点。对象中的属性用来保存节点所需的各种数…

Docker基本概念+命令

Docker基本概念命令 一、Docker是什么&#xff1f;二、为什么Docker技术受欢迎三、Docker核心概念四、Docker安装五、Docker镜像操作1.搜索镜像2.获取镜像3.镜像加速下载4.查看镜像信息5.查看下载的镜像文件信息6.查看下载到本地的所有镜像7.获取镜像的详细信息8.修改镜像标签9…

【复盘与分享】第十一届泰迪杯B题:产品订单的数据分析与需求预测

文章目录 题目第一问第二问2.1 数据预处理2.2 数据集分析2.2.1 训练集2.2.2 预测集 2.3 特征工程2.4 模型建立2.4.1 模型框架和评价指标2.4.2 模型建立2.4.3 误差分析和特征筛选2.4.4 新品模型 2.5 模型融合2.6 预测方法2.7 总结 结尾 距离比赛结束已经过去两个多月了。 整个过…

手机变局2023:一场瞄准产品和技术的“思维革命”

以折叠屏冲高端&#xff0c;已成为中国手机厂商们的共识。 在这个苹果未涉足的领域&#xff0c;国产手机厂商们加快脚步迭代推新&#xff0c;积极抢占机遇。但平心而论&#xff0c;虽然国产折叠屏机型众多&#xff0c;但市场上始终缺乏一款突破性的产品作为标杆&#xff0c;为…

前端监控一vue指令实现埋点

前端监控一vue指令实现埋点 https://v2.vuejs.org/v2/guide/custom-directive.html 自定义指令 需要在main.js中执行 import Vue from vue // 自定义埋点指令 Vue.directive(track, {//钩子函数&#xff0c;只调用一次&#xff0c;指令第一次绑定到元素时调用。在这里可以…

【100天精通python】Day11:面向对象编程_类的定义和使用

目录 1. 面向对象的程序设计概述 2 类的定义和使用 2.1 定义类&#xff1a; 2.2 创建对象实例&#xff1a; 2.3 创建_init_() 方法 2.4 创建类的成员并访问 2.5 访问限制 2.5.1 公开访问&#xff08;Public Access&#xff09;&#xff1a; 2.5.2 私有访问&#xff08;…

深入学习 Redis - 深挖经典数据类型之 set

目录 前言 一、Set 类型 1.1、操作命令 sadd / smembers&#xff08;添加&#xff09; sismember&#xff08;判断存在&#xff09; scard&#xff08;获取元素个数&#xff09; spop&#xff08;删除元素&#xff09; smove&#xff08;移动&#xff09; srem&#x…

剑指27 二叉树的镜像 28.对称的二叉树 26.树的子结构

方法1&#xff1a;队列迭代 方法2&#xff1a;递归 队列迭代&#xff1a; class Solution { public:TreeNode* mirrorTree(TreeNode* root) {queue<TreeNode*> q;if(rootNULL) return root;q.push(root);while(!q.empty()){TreeNode *curq.front();if(!cur) continue;//…

Golang并发控制

开发 go 程序的时候&#xff0c;时常需要使用 goroutine 并发处理任务&#xff0c;有时候这些 goroutine 是相互独立的&#xff0c;需要保证并发的数据安全性&#xff0c;也有的时候&#xff0c;goroutine 之间要进行同步与通信&#xff0c;主 goroutine 需要控制它所属的子gor…

MySQL_2.3【高级查询】超详细讲解

1. distinct关键字 distinct # 在MySQL中&#xff0c;DISTINCT关键字用于消除重复记录&#xff0c;并返回唯一的记录集。 # DISTINCT关键字可以用在SELECT语句的开头&#xff0c;并在查询结果中显示唯一的行。 # 语法如下&#xff1a; select distinct 列1, ... , 列n from t…

vcomp100.dll丢失怎样修复?总结三个简单的修复方法

最近我遇到了一个问题&#xff0c;我的电脑上出现了vcomp100.dll文件丢失的错误。这个错误导致我无法运行一些使用了Microsoft Visual C编写的程序。当我第一次遇到这个问题时&#xff0c;我感到非常困惑和沮丧&#xff0c;因为我不知道如何解决这个问题。 然后&#xff0c;我开…

服务器操作手册——Slurm常用命令

文章目录 引言正文Slurm集群、节点、分区介绍Salloc申请节点并进入查看已经申请的节点终止作业查看集群情况退出节点具体运行问题无法联网问题安装的包找不到 引言 实验室的服务器的操作指令&#xff0c;之前同学写的不够详细&#xff0c;或者说有点乱&#xff0c;这里做一个简…

C++(类与对象)详解 - 1

C&#xff08;类与对象&#xff09;详解 - 1 1.面向过程和面向对象初步认识2.类的引入3.类的定义4.类的访问限定符及封装4.1 访问限定符4.2 封装 5.类的作用域6.类的实例化7.类的对象大小的计算7.1 如何计算类对象的大小7.2 类对象的存储方式7.3 结构体内存对齐规则 8.类成员函…

项目4渗透全过程

网络拓扑图 任务从拓扑图中可以其中一台web服务器可以进行与kali的直接通信。该web服务器是双重网段。也就是拿到该服务器就可以在进行下一步内网操作了。 2008配置&#xff1a; 护卫神主机系统密码&#xff1a;!#Qwe123. sqlserver2008密码&#xff1a;!#a123… 一、信息收…

遥感目标检测(3)-DAL(Dynamic Anchor Learning for Object Detection)

目录 一、概述 二、背景 三、建议 1、旋转RetinaNet 2、动态锚框分布 3、匹配敏感损失 四、实验 一、概述 由于选择正样本锚框进行回归&#xff0c;不一定能够定位真实的GT&#xff0c;而部分负样本回归甚至可以回归到真实的GT&#xff0c;说明相当多的负样本锚框有着准…