码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • DP之字符串算法


    之前写的关于DP问题的一般分析思路:DP之01背包详解
    这篇的话主要是来学习常见的序列问题中用到的DP。

    文章目录

    • 第一种、最长上升子序列
      • 1.1 题目信息:
      • 1.2 分析:
        • 1.2.1 状态表示:
        • 1.2.2 确定状态转移方程
        • 1.2.3 边界:
      • 1.3 代码:
      • 1.4 最长不下降子序列:
    • 第二种:最长公共子序列(LCS)
      • 2.1 题目信息:
      • 2.2 分析:
        • 2.2.1 状态表示:
        • 2.2.2 状态转移方程:
        • 2.2.3 边界:
      • 2.3 代码:
    • 第三种、最长公共子串(LCS)
      • 3.1 题目信息:
      • 3.2 分析:
        • 3.2.1 状态表示:
        • 3.2.2 状态转移方程:
        • 3.2.3 边界:
      • 3.3 代码:

    第一种、最长上升子序列

    1.1 题目信息:

    1.2 分析:

    1.2.1 状态表示:

    f[i]记录所有以第i个数结尾的上升子序列

    1.2.2 确定状态转移方程

    如何更新f[i]的值呢?
    其实在这个类型的题目中是枚举以i为结尾的序列的上一个数是哪一个。于是我们需要变量j从1枚举到i-1,如果a[i]>a[j]并且f[i]>f[j]+1,那么我们认为这是可以用来更新f[i]的值。
    所以可以得出状态转移方程为:

    if(a[i]>a[j])//可以保证是上升序列
    	f[i]=max(f[i],f[j]+1);//通过不断的更新最终保证是最长上升序列
    

    1.2.3 边界:

    f[1]=1;

    1.3 代码:

    # 时间:2022.09.27  21点47分
    #include
    #include
    #include
    using namespace std;
    const int N=100;
    int a[N];
    int f[N];
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        
        for(int i=1;i<=n;i++){
            f[i]=1;//单个数字也可以认为是长度为1的序列
            for(int j=1;j<i;j++)
                if(a[i]>a[j])//保证得到得到上升序列
                    f[i]=max(f[i],f[j]+1);//更新得到的保证是最长上升序列
        }
        int mmax=-1;
        for(int i=1;i<=n;i++)   mmax=max(f[i],mmax);
        cout<<mmax<<endl;
        return 0;
    }
    

    1.4 最长不下降子序列:

    在这里插入图片描述

    和最长上升序列的区别就是元素可以相同。
    只需要将核心代码 f[i] > f[j] 改为 f[i] >= f[j]即可

    第二种:最长公共子序列(LCS)

    2.1 题目信息:

    在这里插入图片描述

    2.2 分析:

    2.2.1 状态表示:

    ==f[i,j]:==所有在第 1个序列的前 i 个字母中出现,且在第二个序列的前 j 个字母中出现的子序列的集合的最大值。

    2.2.2 状态转移方程:

    这种情况下需要看a[i]和b[i]是否在公共序列中:

    1. 若a[i]=b[j],则a[i]与b[j]在公共子序列中,f[i][j]=f[i-1][j-1]+1
    2. 若a[i]!=b[j],且a[i]不在公共子序列中,则可去掉a[i],所以f[i][j]=f[i-1][j]
    3. 若a[i]!=b[j],且b[j]不在公共子序列中,则可去掉b[j],所以f[i][j]=f[i][j-1]
    4. 若a[i]!=b[j],且a[i]和b[j]都不在公共子序列中,则可去掉a[i]和b[j],所以f[i][j]=f[i-1][j-1] ,但是其实可以发现这种情况是包含在2和3中的,所以不用单独写出。

    转移方程:

    1. 如果a[i]!=b[j] 那么 f[i][j]=max(f [i-1] [j],f [i] [j-1] )
    2. 如果a[i]=b[j] 那么 f[i][j]=f [i-1] [j-1]+1

    2.2.3 边界:

    f[0][j]=0,f[i][0]=0;

    2.3 代码:

    // 时间:2022.07.13 17点48分
    #include
    #include
    using namespace std;
    
    const int N=1010;
    int n,m;
    char a[N],b[N];
    int f[N][N];
    int main()
    {
       cin>>n>>m;
       scanf("%s%s",a+1,b+1);
       
       for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            f[i][j]=max(f[i-1][j],f[i][j-1]);
            if(a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1);
        }    
        cout<<f[n][m]<<endl;
        return 0;
    }
    

    第三种、最长公共子串(LCS)

    和最长公共子序列的区别:

    公共子串:字符必须是连续相等的
    公共子序列:字符必须是相等的,可以不连续

    3.1 题目信息:

    在这里插入图片描述

    3.2 分析:

    3.2.1 状态表示:

    只有当两字符串中的字符连续相等时,公共子串的长度才不断增加,否则清零
    状态表示:
    f[i][j]表示以a[i]和b[j]为结尾的公共子串的长度

    3.2.2 状态转移方程:

    我们可以先模拟一下样例:当i=1时
    在这里插入图片描述
    当i=2时:
    在这里插入图片描述
    转移方程:
    我们可以从中找出规律来:只有当a[i]和b[j]相等时才能构成字串,其余的情况都是都不行。

    1. 若a[i]=b[j],则可以构成公共子串,f[i] [j] = f [i-1 ][j-1] +1
    2. 若a[i]!=b[j],则不能构成公共子串,f[i][j] =0

    3.2.3 边界:

    f[0][j]=0
    f[i][0]=0

    3.3 代码:

    // 时间:2022.09.28 21点07分
    #include
    using namespace std;
    int f[100][100];
    int main ()
    {
        string a,b;
        cin>>a>>b;
        int mmax=-1;
        for(int i=1;i<=a.size();i++){
            for(int j=1;j<=b.size();j++){
                if(a[i-1]==b[j-1])//注意此时下标
                    f[i][j]=f[i-1][j-1]+1;
                else f[i][j]=0;
                if(f[i][j]>mmax) mmax=f[i][j];
                //在更新f数组的同时就可以将最大值找到
            }
        }
        cout<<mmax<<endl;
        return 0;
    }
    
  • 相关阅读:
    c 摄像头利用v4l2直接生成avi视频(不利用ffmpeg)
    山海鲸汽车需求调研系统:智慧决策的关键一步
    uniapp如何在页面中只展示一条随机数据
    linux 压缩命令
    【uni-app从入门到实战】get请求、数据缓存、图片上传预览
    进阶JAVA篇- BigDecimal 类的常用API(四)
    本地JS文件批量压缩
    10名IB学生获得满分,新加坡环球印度国际学校成为一匹黑马
    从零开始学习typescript——数据类型
    出口日本的无线产品是做MIC认证还是TELCE认证?有什么区别?
  • 原文地址:https://blog.csdn.net/weixin_53051813/article/details/127079476
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号