dp(六) 线性dp整合 最长(公共子串、公共子序列、上升子序列、回文子串)

news2025/1/15 16:52:41

 1、最大公共子串_牛客题霸_牛客网​编辑

 2、最长上升子序列(一)_牛客题霸_牛客网

 3、最长回文子串_牛客题霸_牛客网

 4、最长公共子序列(二)_牛客题霸_牛客网



#include <iostream>
using namespace std;
#include<vector>
 
int main() 
{
    string str1,str2;
    cin>>str1;
    // 截取划分str1和str2
    int pos = str1.find(',');
    str2 = str1.substr(pos+1);
    str1 = str1.substr(0, pos);
    
    int max = 0;// 记录最长长度
    vector<int> dp(str1.size()+1, 0);
    for(int i = 1; i <= str1.size(); i++)
    {
        // 滚动数组 且需要不断使用之前的值,所以从后往前更新
        for(int j = str2.size(); j >= 1; j--)
        {
            // ij都从1开始所以str1和str2访问i j都要-1操作
            if(str1[i-1] == str2[j-1])
            dp[j] = dp[j-1]+1;// 相等长度加一
            else
            dp[j] = 0;        // 不相等该次即为0
            if(dp[j] > max)
            max = dp[j];        // 不断维护最大值
        }
    }
    cout<<max<<endl;
    return 0;
}
// 64 位输出请用 printf("%lld")

2、最长上升子序列(一)_牛客题霸_牛客网

状态定义 F(i) 表示前i结点的上升子序列的最大长度

状态转移:F(i) = max(F(i), F(j) + arr[i]>arr[j] ? 1 : 0);

初始状态:dp(arr.size(), 1);

返回 max标记的最大值;

心得:慢慢的推导这个状态转移方程就是通过一个个自己通过例子得来的结果中发现规律的。

class Solution {
public:
    int LIS(vector<int>& arr) {
        // write code here
        if(arr.size()==0)
        return 0;
        vector<int> dp(arr.size(), 1);
        int _max = 1;// 记录最大值
        for(int i = 1; i < arr.size(); i++)
        {
            for(int j = 0; j < i; j++)
            {
                if(arr[i] > arr[j])
                    dp[i] = max(dp[i], dp[j]+1);
                if(dp[i] > _max)
                    _max = dp[i]; // 更新最大值
            }
        }
        return _max;
    }
};

 3、最长回文子串_牛客题霸_牛客网

回文分割的写过下面这个更难的最小的回文串分割次数,这道题写起来都不算啥了。

具体下面的解法与时间复杂度的优化可以看下方博客链接,非常详细的演示。http://t.csdn.cn/k22JShttp://t.csdn.cn/k22JS

 【解法一】利用动态规划 较为基础的线性dp

class Solution {
public:
    bool IsPal(int j, int i, string s)
    {
        while(j<i)
        {
            if(s[j++] != s[i--])
            return false;
        }
        return true;
    }
    int getLongestPalindrome(string A) {
        // write code here
        vector<int> dp(A.size(), 1);
        int _max = 1;
        for(int i = 1; i < A.size(); i++)
        {
            for(int j = 0; j <= i; j++)
            {
                // 如果【j, i】为回文串
                if(IsPal(j, i, A))
                {
                    int len = i-j+1;
                    dp[i] = max(dp[i], len);
                    if(dp[i] > _max)_max = dp[i];
                }
            }
        }
        return _max;
    }
};

【解法二】优化一下时间复杂度

解法一的时间复杂度为O(n^3)可以将回文串的判断这里做一个优化,将判断回文串优化为O(1)时间复杂度。将之前的O(n^3)->O(n^2)

class Solution {
public:
    vector<vector<bool>> GetMat(string s)
    {
        int len = s.size();
        vector<vector<bool>> Mat(len, vector<bool> (len, false));
        for(int i = len-1; i >= 0; i--)
        {
            for(int j = i; j <= len-1; j++)
            {
                if(i == j) Mat[i][j] = true;  // 为同一个元素
                else if(i+1 == j) Mat[i][j] = (s[i]==s[j]);  //  为相邻的俩个元素
                else Mat[i][j] = (s[i]==s[j])&&Mat[i+1][j-1];//  俩边相同的条件下,
                                                             //  内部也相同,才为真。
            }
        }
        return Mat;
    }

    int getLongestPalindrome(string A) {
        // write code here
        vector<int> dp(A.size(), 1);
        int _max = 1;
        vector<vector<bool>> Mat = GetMat(A);
        for(int i = 0; i < A.size(); i++)
        {
            for(int j = 0; j <= i; j++)
            {
                // 如果【j, i】为回文串
                if(Mat[j][i])
                {
                    int len = i-j+1;
                    dp[i] = max(dp[i], len);
                    if(dp[i] > _max)_max = dp[i];
                }
            }
        }
        return _max;
    }
};

 4、最长公共子序列(二)_牛客题霸_牛客网

【题解一】当成返回的是最长连续子序列了。。


class Solution {
public:
    string LCS(string s1, string s2) {
        // write code here
        if(s1.empty()||s2.empty())
        return string("-1");
        int max = 0;
        int pos = 0;
        vector<vector<int>> dp(s1.size()+1, vector<int> (s2.size()+1, 0));
        for(int i = 1; i <= s1.size(); i++)
        {
            for(int j = s2.size(); j >= 1; j--)
            {
                if(s1[i-1] == s2[j-1])
                    dp[i][j] = dp[i-1][j-1]+1;
                else dp[i][j] = 0;
                if(dp[i][j] > max)
                {
                    max = dp[i][j];
                    pos = i-1;
                }
            }
        }
        if(max==0) return string("-1");
        return string(s1.substr(pos-max+1, max));
    }
};

【正解】

 状态:F(i, j) 表示s1的前i个字符与s2的前j个字符最长公共子序列

状态转移  F(i, j)  = F(i-1, j-1)+1

                             max(F(i-1, j),F(i, j-1))

初始状态全为0;

当把dp数组初始化好了之后,从右下角开始,找上图中框框位置的元素,满足长度每次第一次发生变化的i下标对应的s1元素入栈。


class Solution {
public:
    string LCS(string s1, string s2) {
        // write code here
        if(s1.empty()||s2.empty())
        return string("-1");
        string res;
        vector<vector<int>> dp(s1.size()+1, vector<int> (s2.size()+1, 0));
        for(int i = 1; i <= s1.size(); i++)
        {
            for(int j = 1; j <= s2.size(); j++)
            {
                if(s1[i-1] == s2[j-1])
                    dp[i][j] = dp[i-1][j-1]+1;
                else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
        stack<char> s;
        int i = s1.size();
        int j = s2.size();
        while(i>=1 && j>=1)
        {
            if(dp[i][j] == dp[i][j-1])
                j--;
            else if(dp[i][j] == dp[i-1][j])
                i--;
            else if(dp[i][j] > dp[i-1][j-1])
            {
                i--;
                j--;
                s.push(s1[i]);
            }
        }
        while(!s.empty())
        {
            res += s.top();
            s.pop();
        }
        return res == "" ? "-1" : res;
    }
};

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

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

相关文章

mysql数据迁移报错问题

mysql8.0.17备份数据库到mysql5.7.26的There was error(s) while executing the queries问题解决&#xff08;数据库高版本向低版本数据迁移解决&#xff09; 问题背景 要将本地的mysql数据库导入到linux中的mysql中&#xff0c;其中&#xff0c;本地mysql数据库的版本是8.0.…

数字硬件建模SystemVerilog-时序逻辑建模(1)RTL时序逻辑的综合要求

数字门级电路可分为两大类&#xff1a;组合逻辑和时序逻辑。锁存器是组合逻辑和时序逻辑的一个交叉点&#xff0c;在后面会作为单独的主题处理。组合逻辑描述了门级电路&#xff0c;其中逻辑块的输出直接反映到该块的输入值的组合&#xff0c;例如&#xff0c;双输入AND门的输出…

N5247A网络分析仪

18320918653 N5247A Agilent N5247A 网络分析仪主要特性与技术指标 10 MHz 至 67 GHz2 端口或 4 端口&#xff0c;具有两个内置信号源可提供 4 端口 110 GHz 单次扫描解决方案110 dB 系统动态范围&#xff0c;32001 个点&#xff0c;32 个通道&#xff0c;5 MHz 中频带宽高输…

MySQL中深入浅出索引

文章目录前言一、索引的常见模型二、InnoDB的索引模型三、索引的维护四、索引的优化覆盖索引联合索引最左前缀原则索引下推前言 我们在看书的时候&#xff0c;打算回看某一个桥段的内容时。这是你肯定会是先翻看书的目录&#xff0c;从目录确定这段内容的位置&#xff0c;然后…

爬虫利用多线程快速爬取数据

一般单线程爬数据太慢了话&#xff0c;就采用多线程。 一般要根据两种情形来选择 自定义线程线程池 往往最关键的地方在&#xff0c;多个线程并发执行后&#xff0c;是否需要线性的返回结果。也就是先调用的线程&#xff0c;返回的结果要在前面。 或者说&#xff0c;某个对…

mysql简单数据查询——数采数据电量与耗料的日统计

目录 前言 步骤1&#xff1a;date_format函数 步骤2&#xff1a;concat函数 步骤3、4&#xff1a;查询中使用变量 完整代码 前言 在数采数据已写入mysql数据库中后&#xff0c;进行数据处理&#xff0c;统计电量与耗料数据 由于数据库版本较低&#xff0c;无法使用较新的…

华为策略路由实验配置

配置接口相关的IP地址&#xff0c;并配置IGP路由协议使得全网互通 AR1配置接口策略路由 对经过本地转发的路由生效&#xff0c;对本地始发的路由不生效 配置nqa检测下一跳状态 nqa test-instance PC1 icmptrace nqa的管理者为PC1&#xff0c;NQA的测试例名为icmptrace test-…

全国青少年软件编程(Scratch)等级考试二级考试真题2022年12月——持续更新.....

1.一个骰子,从3个不同角度看过去的点数如图所示,请问5的对面是什么点数?( ) A.1 B.3 C.4 D.6 正确答案:A 答案解析: 根据图三,用右手定则,大拇指朝上指向6所对的方向,其余四指握起来表示旋转方向,可以看到先5后2,然后把这个姿势对应到图1中,就知道1的对面是5…

C语言进阶(8)——动态内存空间管理

前言 文章目录前言1.为什么存在动态内存分配2.动态内存函数的介绍2.1 malloc函数2.2 free函数2.3 calloc2.4realloc3 常见的动态内存错误4.经典笔试题题目 1&#xff1a;题目 2&#xff1a;题目 3&#xff1a;题目 4&#xff1a;5.C/C程序的内存开辟6.柔性数组6.1 定义6.2 柔性…

1.5、中断和异常

整体框架 1、中断的概念和作用 当中断发生时&#xff0c;CPU 立即进入核心态\color{red}核心态核心态 当中断发生后&#xff0c;当前运行的进程暂停运行&#xff0c;并由操作系统内核对中断进行处理 对于不同的中断信号&#xff0c;会进行不同的处理 发生了中断&#xff0c…

记录--“非主流” 的纯前端性能优化

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 性能优化一直是前端研究的主要课题之一&#xff0c;因为不仅直接影响用户体验&#xff0c;对于商业性公司&#xff0c;网页性能的优劣更关乎流量变现效率的高低。例如 DoubleClick by Google 发现&…

MD5加密

MD5加密 md5加密 明文 加密变成 128位二进制 --> 32位16进制字符串的密文 MD5特征: 明文一样, 得到密文一样密文一样, 推出明文一样明文不一样, 得到密文不一样 缺点&#xff1a; 现在网上有很多暴力破解的网址&#xff0c;直接使用md5加密还是不太安全 为了提高安全性&am…

Linux常用命令——vmstat命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) vmstat 显示虚拟内存状态 补充说明 vmstat命令的含义为显示虚拟内存状态&#xff08;“Viryual Memor Statics”&#xff09;&#xff0c;但是它可以报告关于进程、内存、I/O等系统整体运行状态。 语法 vmst…

Java高并发编程实战,异步注解@Async自定义线程池

一、Async注解 Async的作用就是异步处理任务。 在方法上添加Async&#xff0c;表示此方法是异步方法&#xff1b; 在类上添加Async&#xff0c;表示类中的所有方法都是异步方法&#xff1b; 使用此注解的类&#xff0c;必须是Spring管理的类&#xff1b; 需要在启动类或配置类…

ELK日志(1)

Elasticsearch开源分布式搜索引擎&#xff0c;它的特点有&#xff1a;分布式&#xff0c;零配置&#xff0c;自动发现&#xff0c;索引自动分片&#xff0c;索引副本机制&#xff0c;restful 风格接口&#xff0c;多数据源&#xff0c;自动搜索负载等。RESTFUL特点包括&#xf…

MES系统之工控

MES系统之工控 要控制MES系统首先要对他有个了解。MES系统最早由1990年&#xff0c;由美国先进制造研究中心AMR提出的&#xff0c;当时中文意思叫制造执行系统概念。直到1997年&#xff0c;MESA(制造执行系统协会)提出了MES功能组件和继承模型&#xff0c;到20世纪90年代初期&a…

动态内存管”家“

&#x1f40b;动态内存管理&#x1f996;动态内存分配存在的意义&#x1f996;动态内存函数的介绍&#x1f424;malloc和free&#x1f424;calloc&#x1f424;realloc&#x1f996;常见动态内存错误&#x1f424;对空指针的解引用操作&#x1f424;对动态开辟空间的越界访问&a…

springMVC的响应

SpringMVC接收到请求和数据后&#xff0c;进行一些了的处理&#xff0c;当然这个处理可以是转发给Service&#xff0c;Service层再调用Dao层完成的&#xff0c;不管怎样&#xff0c;处理完以后&#xff0c;都需要将结果告知给用户。 对于响应&#xff0c;主要就包含两部分内容&…

关于 sensor hdr 模式下不出图/出图异常的排查方法

1、问题背景&#xff1a;有项目调试过 ov02k10&#xff08;1920*1080&#xff09;和 sc301IoT&#xff08;2048*1536&#xff09;两款 sensor, 都有出现 hdr 模式下出图异常或者不出图的问题&#xff0c;总结下排查过程及注意事项&#xff1b;2、问题现象&#xff1a;a、ov02k1…

Odoo 16 企业版手册 - 库存管理之寄售

寄售 使用“「设置」”菜单下提供的「寄售」选项&#xff0c;可以对库存中储存的产品设置所有者。产品将由零售商销售&#xff0c;但产品的实际所有权将由供应商持有&#xff0c;直到产品出售给客户。通过这种方法&#xff0c;您可以轻松地将未售出的产品退还给供应商。在寄售的…