多维动态规划-面试高频!-最长公共子序列和最长公共子串、回文串-c++实现和详解

1143. 最长公共子序列

中等

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

示例 1:

输入:text1 = "abcde", text2 = "ace" 
输出:3  
解释:最长公共子序列是 "ace" ,它的长度为 3 。

示例 2:

输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc" ,它的长度为 3 。

示例 3:

输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0 。

提示:

  • 1 <= text1.length, text2.length <= 1000
  • text1text2 仅由小写英文字符组成。

解法

  • 定义 dp [ i ] [ j ] 表示 text1[0:i-1] 和 text2[0:j-1] 的最长公共子序列。 状态定义特别重要,dp[ i] [ j] 其中i和j都是开区间,所以dp[0] [0]=0只是表示两个空串的最长公共子序列,这种方式省去了所有的初始化
class Solution {
public:int longestCommonSubsequence(string text1, string text2) {// 状态定义特别重要// dp[i][j] i和j都是开区间// 如果上一个都相等,就给下一个赋值// 遍历只是表现形式int M = text1.size();int N = text2.size();// dp的初始化vector<vector<int>> dp(M + 2, vector<int>(N + 2, 0));for (int i = 1; i <= M; i++) {for (int j = 1; j <= N; j++) {if (text1[i - 1] == text2[j - 1])dp[i][j] = dp[i - 1][j - 1] + 1;elsedp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);}}return dp[M][N];}
};

BM66 最长公共子串

题目链接-牛客

  • 这道题我面试碰到了,当时不会做!没想到力扣没有这道题!

描述

给定两个字符串str1和str2,输出两个字符串的最长公共子串

题目保证str1和str2的最长公共子串存在且唯一。

数据范围: 1≤∣𝑠𝑡𝑟1∣,∣𝑠𝑡𝑟2∣≤50001≤∣str1∣,∣str2∣≤5000
要求: 空间复杂度 𝑂(𝑛2)O(n2),时间复杂度 𝑂(𝑛2)O(n2)

示例1

输入:

"1AB2345CD","12345EF"

复制

返回值:

"2345"

复制

备注:

1≤∣𝑠𝑡𝑟1∣,∣𝑠𝑡𝑟2∣≤5 0001≤∣str1∣,∣str2∣≤5000

解法

  • 本题的区别是子序列和子串的定义不同,所以本题如果两个字符不同的话就应该直接把dp清零!

  • 我自己的代码如下:

    #include <vector>
    class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** longest common substring* @param str1 string字符串 the string* @param str2 string字符串 the string* @return string字符串*/string LCS(string str1, string str2) {// write code hereint M = str1.size();int N = str2.size();int maxx = 0;vector<vector<int>>dp(M + 2, vector<int>(N + 2, 0)); //初始化、string res;for (int i = 1; i <= M; i++) {for (int j = 1; j <= N; j++) {if (str1[i - 1] == str2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;if (dp[i][j] > maxx) {maxx = dp[i][j];int l = dp[i][j];res = str1.substr(i - l, l);}} else dp[i][j] = 0;}}return res;}
    };
    

后来看到别人更好的代码:

#include <iostream>
#include <vector>
#include <string>
using namespace std;string LCS(const string& str1, const string& str2) {int maxLength = 0; // 记录最长公共子串的长度int maxLastIndex = 0; // 记录最长公共子串最后一个字符在字符串str1中的位置// 创建二维动态规划表,大小为(str1.length() + 1) x (str2.length() + 1)vector<vector<int>> dp(str1.length() + 1, vector<int>(str2.length() + 1, 0));// 遍历str1和str2的每一个字符for (int i = 0; i < str1.length(); i++) {for (int j = 0; j < str2.length(); j++) {// 当字符相等时,更新dp表的值if (str1[i] == str2[j]) {dp[i + 1][j + 1] = dp[i][j] + 1;// 如果当前公共子串的长度大于之前记录的最大值,则更新最大长度和最后一个字符的位置if (dp[i + 1][j + 1] > maxLength) {maxLength = dp[i + 1][j + 1];maxLastIndex = i;}} else {// 当字符不相等时,将dp表中的值设为0,表示没有公共子串dp[i + 1][j + 1] = 0;}}}// 使用substr函数截取最长公共子串return str1.substr(maxLastIndex - maxLength + 1, maxLength);
}

这里补充一个点,求回文串、回文数等等的通法:双指针中心扩散

最长回文串

  • 我先贴一份我自己写的代码,我的初始想法是,把s做一个reverse,然后求s1和s的最长公共子串,就是回文串
class Solution {
public:string longestPalindrome(string s) {// 最长回文子串=reverse的最长公共子串!string s1 = s;reverse(s.begin(), s.end());int M = s.size();vector<vector<int>> dp(M + 1, vector<int>(M + 1, 0));int maxlen = 0;int end = 0;for (int i = 1; i <= M; i++) {for (int j = 1; j <= M; j++) {if (s[i - 1] == s1[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;if (dp[i][j] > maxlen) {maxlen = max(maxlen, dp[i][j]); // 最大值end = i - 1;}} else {dp[i][j] = 0;}}}return s.substr(end - maxlen + 1, maxlen);}
};
  • 样例都过了,卡在了后面的一个样例,说明这个方法是错的!
    在这里插入图片描述
  • 下面附正确的代码(已经写上完整注释):
class Solution {
public:// 辅助函数,用于计算以 s[l] 和 s[r] 为中心的最长回文子串的长度int help(string s, int l, int r) {int len = s.size();// 当 l 和 r 不超出范围,并且 s[l] == s[r] 时,向外扩展while (l >= 0 && r < len && s[l] == s[r]) {l--;  // 左边指针左移r++;  // 右边指针右移}// 返回回文子串的长度,注意此时 l 和 r 已经多走了一步return r - l - 1; // 回文串的长度为 r - l - 1}// 主函数,返回最长的回文子串string longestPalindrome(string s) {int len = s.size();  // 字符串长度int begin = 0;  // 记录最长回文子串的起始位置int maxlen = 0; // 记录最长回文子串的长度// 遍历字符串中的每个字符,以它们作为回文的中心for (int i = 0; i < len; i++) {// 以 i 为中心扩展,找奇数长度的回文子串int len1 = help(s, i, i);// 以 i 和 i+1 为中心扩展,找偶数长度的回文子串int len2 = help(s, i, i + 1);// 更新最长回文子串的长度和起始位置if (len1 > maxlen || len2 > maxlen) {if (len1 > len2) {// 如果奇数长度的回文子串更长maxlen = len1;  // 更新最大长度begin = i - (len1 - 1) / 2; // 计算起始位置} else {// 如果偶数长度的回文子串更长maxlen = len2;  // 更新最大长度begin = i - (len2 - 2) / 2; // 计算起始位置}}}// 返回从起始位置开始的最大回文子串return s.substr(begin, maxlen);}
};

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

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

相关文章

力扣1049-最后一块石头的重量II(Java详细题解)

题目链接&#xff1a;1049. 最后一块石头的重量 II - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完01背包&#xff0c;所以现在的题解都是以01背包问题为基础再来写的。 如果大家不懂…

FPGA实现串口升级及MultiBoot(二)FPGA启动流程

这个系列开篇肯定要先了解FPGA的启动流程&#xff0c;试想一下&#xff1a;我想实现MultiBoot&#xff0c;那么我应该在什么时候开始升级&#xff0c;升级失败后FPGA进行了哪些操作&#xff0c;以及怎么回到Golden区&#xff1f; 还有一个问题&#xff0c;就是我硬件打板回来&a…

Selenium 实现图片验证码识别

前言 在测试过程中&#xff0c;有的时候登录需要输入图片验证码。这时候使用Selenium进行自动化测试&#xff0c;怎么做图片验证码识别&#xff1f;本篇内容主要介绍使用Selenium、BufferedImage、Tesseract进行图片 验证码识别。 环境准备 jdk&#xff1a;1.8 tessdata&…

深度学习--对抗生成网络(GAN, Generative Adversarial Network)

对抗生成网络&#xff08;GAN, Generative Adversarial Network&#xff09;是一种深度学习模型&#xff0c;由Ian Goodfellow等人在2014年提出。GAN主要用于生成数据&#xff0c;通过两个神经网络相互对抗&#xff0c;来生成以假乱真的新数据。以下是对GAN的详细阐述&#xff…

如果电脑一直提示微软账号登录……

前言 今天小白接了个电脑故障问题&#xff1a;电脑提示微软账号登录&#xff0c;然后经过各种操作…… 电脑重启之后就变成了这样&#xff1a; 按理说&#xff0c;登录了微软账号之后&#xff0c;Windows系统要进入到桌面就必须有一个输入密码验证的过程&#xff0c;但这个界…

Harmony OS DevEco Studio 如何导入第三方库(以lottie为例)?-- HarmonyOS自学2

在做鸿蒙开发时&#xff0c;离不开第三方库的引入 一.有哪些支持的Harmony OS的 第三方库&#xff1f; 第三方库下载地址&#xff1a; 1 tpc_resource: 三方组件资源汇总 2 OpenHarmony三方库中心仓 二. 如何加入到DevEco Studio工程 以 lottie为例 OpenHarmony-TPC/lot…

nginx 新建一个 PC web 站点

注意&#xff1a;进行实例之前必须完成nginx的源码编译。&#xff08;阅读往期文章完成步骤&#xff09; 1.编辑nginx的配置文件&#xff0c;修改内容 [rootlocalhost ~]# vim /usr/local/nginx/conf/nginx.conf 2.创建新目录/usr/local/nginx/conf.d/&#xff0c;编辑新文件…

基于飞腾平台的Hive的安装配置

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…

通信工程学习:什么是PCM脉冲编码调制、DPCM差分脉冲编码调制、ADPCM自适应差分脉冲编码调制

PCM脉冲编码调制、DPCM差分脉冲编码调制、ADPCM自适应差分脉冲编码调制 PCM、DPCM、ADPCM是音频编码技术中的三种重要方式&#xff0c;它们在音频信号的数字化、压缩和传输中起着关键作用。以下是对这三种技术的详细解释&#xff1a; 一、PCM&#xff08;Pulse Code Modulatio…

2024数学建模国赛选题建议+团队助攻资料(已更新完毕)

目录 一、题目特点和选题建议 二、模型选择 1、评价模型 2、预测模型 3、分类模型 4、优化模型 5、统计分析模型 三、white学长团队助攻资料 1、助攻代码 2、成品论文PDF版 3、成品论文word版 9月5日晚18&#xff1a;00就要公布题目了&#xff0c;根据历年竞赛题目…

[C#学习笔记]注释

官方文档&#xff1a;Documentation comments - C# language specification | Microsoft Learn 一、常用标记总结 1.1 将文本设置为代码风格的字体&#xff1a;<c> 1.2 源代码或程序输出:<code> 1.3 异常指示:<exception> 1.4 段落 <para> 1.5 换行&…

Reflection 70B:震撼AI行业的开源模型

随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;开源与闭源模型的竞争变得越来越激烈。近日&#xff0c;Reflection 70B模型的发布在AI行业引发了巨大的震动。这款拥有70亿参数的开源模型不仅在多项基准测试中取得了优异成绩&#xff0c;还在很多情况下超越…

滑动窗口系列(同向双指针)/9.7

新的解题思路 一、三数之和的多种可能 给定一个整数数组 arr &#xff0c;以及一个整数 target 作为目标值&#xff0c;返回满足 i < j < k 且 arr[i] arr[j] arr[k] target 的元组 i, j, k 的数量。 由于结果会非常大&#xff0c;请返回 109 7 的模。 输入&…

【阿里云】个人认证与公司认证

个人认证和企业认证的区别 更新时间&#xff1a;2024-05-20 09:32:52 本文档主要介绍个人认证账号和企业认证账号的区别。 账号实名认证分为个人实名认证和企业实名认证。 个人账号认证&#xff0c;请选择认证类型为 个人&#xff0c;支持个人支付宝授权认证和个人扫脸认证。…

使用cage工具包生成验证码

目录 1. 导入依赖2. 控制类3. 测试 1. 导入依赖 <!-- 验证码工具 --><dependency><groupId>com.github.cage</groupId><artifactId>cage</artifactId><version>1.0</version></dependency>2. 控制类 RestControl…

探索 RAD:5 个最佳实践案例解析

天下武功&#xff0c;唯快不破&#xff01;应用开发&#xff0c;唯速称王&#xff01; 在当今快速发展的科技环境中&#xff0c;企业面临的挑战不断升级。传统的应用开发方法往往因其复杂的流程和较长的开发周期而无法满足快速变化的市场需求。在这种背景下&#xff0c;快速应…

Mybatis【分页插件,缓存,一级缓存,二级缓存,常见缓存面试题】

文章目录 MyBatis缓存分页延迟加载和立即加载什么是立即加载&#xff1f;什么是延迟加载&#xff1f;延迟加载/懒加载的配置 缓存什么是缓存&#xff1f;缓存的术语什么是MyBatis 缓存&#xff1f;缓存的适用性缓存的分类一级缓存引入案例一级缓存的配置一级缓存的工作流程一级…

【JavaSE基础】Java 基础知识

Java 转义字符 Java 常用的转义字符 在控制台&#xff0c;输入 tab 键&#xff0c;可以实现命令补全 转义字符含义作用\t制表符一个制表位&#xff0c;实现对齐的功能\n &#xff1a;换行符\n换行符一个换行符\r回车符一个回车键 System.out.println(“韩顺平教育\r 北京”);&…

java实现,PDF转换为TIF

目录 ■JDK版本 ■java代码・实现效果 ■POM引用 ■之前TIF相关的问题&#xff08;两张TIF合并&#xff09; ■对于成果物TIF&#xff0c;需要考虑的点 ■问题 ■问题1&#xff1a;无法生成TIF&#xff0c;已解决 ■问题2&#xff1a;生成的TIF过大&#xff0c;已解决 …

MySQL之DQL-分组函数

1、分组函数 1. 分组函数语法 分组函数也叫聚合函数。是对表中一组记录进行操作&#xff0c;每组只返回一个结果。我们只讲如下5个常用的分组函数&#xff1a; 分组函数 含义 MAX 求最大值 MIN 求最小值 SUM 求和 AVG 求平均值 COUNT 求个数 分组函数的语法如下…