当前位置: 首页 > news >正文

动态规划学习——通符串匹配,正则表达式

目录

​编辑

一,通符串匹配

1.题目

2.题目接口

3,解题思路及其代码

二,正则表达

 1.题目

2.题目接口

3.解题思路及其代码

三,交错字符串

 1.题目

2,题目接口

3.解题思路及其代码


一,通符串匹配

1.题目

给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 '?' 和 '*' 匹配规则的通配符匹配:

  • '?' 可以匹配任何单个字符。
  • '*' 可以匹配任意字符序列(包括空字符序列)。

判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。

 

示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = "*"
输出:true
解释:'*' 可以匹配任意字符串。

示例 3:

输入:s = "cb", p = "?a"
输出:false
解释:'?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。

提示:

  • 0 <= s.length, p.length <= 2000
  • s 仅由小写英文字母组成
  • p 仅由小写英文字母、'?' 或 '*' 组成

2.题目接口

class Solution {
public:bool isMatch(string s, string p) {}
};

3,解题思路及其代码

在做动态规划问题时一般都是按照以下几步来走的:

1.确定状态转移方程

 像这种两个字符串的问题,一般都是定义二维的dp表按照两个字符串的第i和j下标位置来解决问题的。所以在这里定义dp[i][j]表示p在区间[1,j]中的字符是否存在能够匹配s在[1,i]中的字符。

2.状态转移方程

以s的第i个位置,p的第j个位置为研究对象来研究问题。此时分三种情况:1.s[i] == p[j],或者p[j] == '?',在这种情况下dp[i][j] = dp[i-1][j-1]。

2.p[j] == "*",在这种情况下就要看这个*可以顶替掉多少个s中的字符了:

顶替0个:dp[i][j] = dp[i][j-1]

顶替1个:dp[i][j] = dp[i-1][j-1]

顶替2个:dp[i][j] = dp[i-2][j-1]

顶替3个:dp[i][j] = dp[i-3][j-1]......

在以上i种情况下,我们只要找到一个为真便可以了。所以dp[i][j] = dp[i][j-1]||dp[i-1][j-1]||dp[i-2][j-1]||dp[i-3][j-1].....。但是这样表示的话就需要遍历一遍,所以我们必须要优化以上状态表达,优化成为dp[i][j] = dp[i][j-1]||dp[i-1][j]。通过数学推导得知(将dp[i][j-1]后面的表达式转为一个状态表示)。

3.s[i]!=p[j]并且不是以上情况,在这种条件下dp[i][j]直接就是false。

3.初始化

1.在字符串问题里,我们一般会在字符串的开头加上一个' '。

 2.因为*是可以匹配空的,所以当s字符串为空串时p为空串或者p全为*时也是可以匹配的。

初始化如下:

s = ' '+s;
p = ' '+p;dp[0][0] = true;
//初始化:当我的s是一个空串时,我的p都是*
for(int i = 1;i<n+1;i++) if(dp[0][i-1]&&p[i] == '*') dp[0][i] = true;

4.填表顺序

根据状态转移方程很容易得出dp表的填写顺序是从左到右,从上到下。

5.返回值

 根据状态表示可知返回值是dp[m][n](m表示s的长度,n表示p的长度)    

代码:

class Solution {
public:bool isMatch(string s, string p) {int m = s.size();int n = p.size();vector<vector<bool>>dp(m+1,vector<bool>(n+1));//dp[i][j]表示s,p分别以i,j结尾能不能完全匹配s = ' '+s;p = ' '+p;dp[0][0] = true;//初始化:当我的s是一个空串时,我的p都是*for(int i = 1;i<n+1;i++) if(dp[0][i-1]&&p[i] == '*') dp[0][i] = true;//以i,j为结尾研究问题for(int i = 1;i<m+1;i++){for(int j = 1;j<n+1;j++){//分两种情况if(p[j] == s[i]||p[j] == '?'){dp[i][j] = dp[i-1][j-1];}else if(p[j] == '*'){//这颗*可以若干个字符,那可以配0个或者无数个得到的状态转移方程如下//如果不匹配dp[i][j] = dp[i][j-1]//如果匹配1个dp[i][j] = dp[i-1][j-1]//如果匹配两个dp[i][j] = dp[i-2][j-1]//.......//在上面的情况中我们只要找到一种便可以//dp[i][j] = dp[i][j-1]||dp[i-1][j-1]||dp[i-2][j-1]||dp[i-3][j-1]......//优化:将上面的i个表达式变成n个表达式表示:dp[i][j] = dp[i][j-1]||dp[i-1][j]       dp[i][j] = dp[i-1][j]||dp[i][j-1];}}} return dp[m][n];}
};

二,正则表达

 1.题目

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

  • '.' 匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

 

示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

示例 3:

输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。

提示:

  • 1 <= s.length <= 20
  • 1 <= p.length <= 20
  • s 只包含从 a-z 的小写字母。
  • p 只包含从 a-z 的小写字母,以及字符 . 和 *
  • 保证每次出现字符 * 时,前面都匹配到有效的字符

2.题目接口

class Solution {
public:bool isMatch(string s, string p) {}
};

3.解题思路及其代码

但是这道题跟第一道题何其相似啊!!!'.'和'?'匹配规则是一样的,但是注意两个题目的'*'的匹配规则是是不一样的。所以在'*"和初始化处就要稍加改造了,改造如下:

初始化

 for(int i = 2;i<n+1;i+=2) if(dp[0][i-2]&&p[i] == '*') dp[0][i] = true;

当遇到"*"时填表情况如下

                else if(p[j] == '*'){//按照题意在*前面一定有字符if(p[j-1] == '.')//无敌匹配{dp[i][j] = dp[i][j-2]||dp[i-1][j];}else//不是.{//判断后再匹配if(p[j-1] == s[i]){dp[i][j] = dp[i][j-2]||dp[i-1][j];}else{dp[i][j] = dp[i][j-2];}}

解题代码如下

class Solution {
public:bool isMatch(string s, string p) {int m = s.size();int n = p.size();//经典加上空格s = ' '+s;p = ' '+p;//经典二维dp表vector<vector<bool>>dp(m+1,vector<bool>(n+1));dp[0][0] = true;//初始化:当s为空串时for(int i = 2;i<n+1;i+=2) if(dp[0][i-2]&&p[i] == '*') dp[0][i] = true;for(int i = 1;i<m+1;i++){for(int j = 1;j<n+1;j++){//分情况讨论if(p[j] == '.'||s[i] == p[j]){//i,j位置匹配上了就得看dp[i-1][j-1]dp[i][j] = dp[i-1][j-1];}else if(p[j] == '*'){//按照题意在*前面一定有字符if(p[j-1] == '.')//无敌匹配{dp[i][j] = dp[i][j-2]||dp[i-1][j];}else//不是.{//判断后再匹配if(p[j-1] == s[i]){dp[i][j] = dp[i][j-2]||dp[i-1][j];}else{dp[i][j] = dp[i][j-2];}}}}}return dp[m][n];}
};

三,交错字符串

 1.题目

给定三个字符串 s1s2s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。

两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:

  • s = s1 + s2 + ... + sn
  • t = t1 + t2 + ... + tm
  • |n - m| <= 1
  • 交错 是 s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...

注意:a + b 意味着字符串 a 和 b 连接。

示例 1:

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出:true

示例 2:

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出:false

示例 3:

输入:s1 = "", s2 = "", s3 = ""
输出:true

提示:

  • 0 <= s1.length, s2.length <= 100
  • 0 <= s3.length <= 200
  • s1s2、和 s3 都由小写英文字母组成

进阶:您能否仅使用 O(s2.length) 额外的内存空间来解决它?

2,题目接口

class Solution {
public:bool isInterleave(string s1, string s2, string s3) {}
};

3.解题思路及其代码

在看到三个字符串时,我就已经犯蒙了。感觉二维的dp表好像已经解决不了问题了,但是其实是可以解决问题的。解决步骤如下:

1,状态表示

仍然是开一个二维dp表dp[][]。仍然以s1的第i个位置和s2的第j个位置为研究对象研究问题。dp[i][j]表示s1的【1,i]区间和s2的【1,j】区间的字符能不能组成s3的【1,i+j】区间的字符。

2.状态转移方程

在这里我们也是分两种情况来讨论:

1,当s1[i] == s3[i+j]时,dp[i][j] = dp[i-1][j]。

2, 当s2[j] == s3[i+j]时,dp[i][j] = dp[i][j-1]。

3, 当以上两种情况都不成立的话,dp[i][j] = false。

所以dp[i][j] = (s1[i]==s3[i+j]&&dp[i-][j])&&(s2[j] == s3[i+j]&&dp[i][j-1])。

3,初始化

为了让下标对应所以得在每个字符的前面加上" "。

  //加上空格,因为空格有意义s1 = " "+s1;s2 = " "+s2;s3 = " "+s3;

当s1和s2都是空串时,能够组成空串

//初始化
dp[0][0] = true;

当有一个串为空时,另一个串要和s3一一匹配

      for(int i =1;i<m+1;i++)//代表s2为空串{if(s1[i] == s3[i]){dp[i][0] = true;}else {break;}}for(int i =1;i<n+1;i++)//代表s1为空串{if(s2[i] == s3[i]){dp[0][i] = true;}else{break;}}

4,填表顺序

按照状态转移方程可知填表顺序为:从上到下,从左到右。

5,返回值

返回dp[m][n]

代码如下

class Solution {
public:bool isInterleave(string s1, string s2, string s3) {int m = s1.size();int n = s2.size();if(m+n!=s3.size()) return false;//二维数组表示以i,j位置为结尾能够组成s3的i+jvector<vector<bool>>dp(m+1,vector<bool>(n+1));//加上空格,因为空格有意义s1 = " "+s1;s2 = " "+s2;s3 = " "+s3;//初始化dp[0][0] = true;for(int i =1;i<m+1;i++)//代表s2为空串{if(s1[i] == s3[i]){dp[i][0] = true;}else {break;}}for(int i =1;i<n+1;i++)//代表s1为空串{if(s2[i] == s3[i]){dp[0][i] = true;}else{break;}}//经典以i,j位置为研究对象for(int i = 1;i<m+1;i++){for(int j = 1;j<n+1;j++){dp[i][j] = (s1[i] == s3[i + j] && dp[i - 1][j])|| (s2[j] == s3[i + j] && dp[i][j - 1]);}}return dp[m][n];}
};

相关文章:

动态规划学习——通符串匹配,正则表达式

目录 ​编辑 一&#xff0c;通符串匹配 1.题目 2.题目接口 3&#xff0c;解题思路及其代码 二&#xff0c;正则表达 1.题目 2.题目接口 3.解题思路及其代码 三&#xff0c;交错字符串 1.题目 2&#xff0c;题目接口 3.解题思路及其代码 一&#xff0c;通符串匹配 1…...

【数据开发】Hive 多表join中的条件过滤与指定分区

1、条件过滤 left join 中 on 后面加条件 where 和 and 的区别 1、 on条件是在生成临时表时使用的条件&#xff0c;它不管and中的条件是否为真&#xff0c;都会保留左边表中的全部记录。2、where条件是在临时表生成好后&#xff0c;再对临时表进行过滤的条件。这时已经没有le…...

基于Java SSM框架实现高校人事管理系统项目【项目源码】计算机毕业设计

基于java的SSM框架实现高校人事管理系统演示 JSP技术介绍 JSP技术本身是一种脚本语言&#xff0c;但它的功能是十分强大的&#xff0c;因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时&#xff0c;它可以使显示逻辑和内容分开&#xff0c;这就极大的方便了用户的需…...

[C++] 模板进阶(非类型模板参数,特化,分离编译)

文章目录 1、非类型模板参数2、模板的特化2.1 什么是模板特化2.2 函数模板特化2.3 类模板的实例化2.3.1 全特化2.3.2 偏特化 3、模板分离编译3.1 什么是分离编译3.2 模板的分离编译3.3 解决方法 4、模板总结 1、非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即…...

C++ this指针

通常情况下&#xff0c;类的成员函数都只涉及一个对象&#xff0c;即调用它的对象。但有时候方法可能涉及到两个对象&#xff0c;在这种情况就需要使用到C的this指针。 class Stock { private: ... double total_val; ... public: double total() const {return total_val;} }…...

解决Sortable拖动el-table表头时,由于选择列造成的拖拽顺序错乱的bug

原因 由于我的表头是由数组循环遍历生成的&#xff0c;而选择列不在数组内&#xff0c;只能在循环外定义el-table-column&#xff0c;造成拖动时索引错乱错误代码 <el-tableheader-dragend"headerDragend"id"out-table":data"state.sliceTable&quo…...

Plantuml之类图语法介绍(十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…...

深入Docker命令行:探索常用命令和实用技巧

Docker命令行界面是每个容器开发者的得力工具。在这篇文章中&#xff0c;将深入探讨一系列常用的Docker命令&#xff0c;以及一些实用技巧&#xff0c;通过更丰富的示例代码&#xff0c;帮助大家更全面地理解和运用Docker命令行工具。 1. Docker基本命令 1.1 镜像操作 深入了…...

qt 容器QVector,QMap,QHash的常见使用与该迭代器的简单介绍

一. QVector容器是一个动态数组&#xff0c;可以容纳任意数量的元素,在相邻的内存中存储给定的数据类型作为一组数据,在QVector前部或中间位置插入元素都会导致内存中大量的数据元素移动,这使得操作速度会减慢.可使用迭代器对这组数据进行访问. 和其他的容器类型类似,QVector…...

两线制无源 4-20mA 回路供电隔离变送器

两线制无源 4-20mA 回路供电隔离变送器 一入一出两线制无源 4-20mA 回路供电隔离变送器 概述&#xff1a;JSD TAW-1001D-100L-F 系列隔离变送器是 4-20mA 两线制回路供电的电流隔离变送配电器,该隔离变送器采用电磁隔离技术,并通过输入端馈电方式,给输入端两线制仪器仪表设备供…...

强化学习优质博客记录(随缘更新)

杂记 速成深度强化学习的人可能陷入的几个误区(2023-03更新) DQN DQN表现稳定提升和收敛的技巧集锦 TRPO 如何看懂TRPO里所有的数学推导细节? PPO The 37 Implementation Details of Proximal Policy Optimization强化学习算法中&#xff0c;PPO算法是不是就是加了重要…...

RabbitMQ-hello

0. pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0…...

案例044:基于微信小程序的消防隐患在线举报系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…...

MES系统需要具备哪些性能方面的需求?

MES系统需要具备哪些“性能需求”&#xff1f;关于这个问题&#xff0c;我觉得有必要先和大家解释一下&#xff0c;到底什么是性能需求&#xff1f;性能需求在MES系统的作用是什么&#xff1f;讲明白了这2点&#xff0c;问题自然而然就解决了。 什么是性能需求&#xff1f; 通…...

数据在内存中的存储(整型篇)

1.辨析原码反码补码&#xff1a; 1.原码&#xff1a;有32位&#xff08;int类四个字节&#xff0c;一个字节八个比特位&#xff09;&#xff0c;第一位是符号位&#xff0c;0正1负&#xff0c;其余为二进制位。 2.计算一般是对原码进行计算&#xff0c;但在负数计算使用原码会导…...

大一作业习题

第一题&#xff1a;答案&#xff1a; #include <stdio.h> void sort(int a[], int m) //将数组a的前m个元素(从小到大)排序 {int i 0;for (i 0; i < m - 1; i){int j 0;int flag 1;for (j 0; j < m - 1 - i; j){if (a[j] > a[j 1]){int t 0;t a[j];…...

Python大模型TensorFlow/PyTorch/Scikit-learn/Keras/OpenCV/Gensim

Python 作为一种高级编程语言&#xff0c;可以用于开发各种大小的模型。以下是一些常见的 Python 大模型&#xff0c;以及它们的优势、劣势和使用场景&#xff1a; TensorFlow&#xff1a; 优势&#xff1a;TensorFlow 是一个非常流行的深度学习库&#xff0c;具有高度的可扩…...

TCP 和 UDP 区别? 2、TCP/IP 协议涉及哪几层架构? 3、描述下 TCP 连接 4 次挥手的过程?为什么要 4 次挥手?

文章目录 1、TCP 和 UDP 区别&#xff1f;2、TCP/IP 协议涉及哪几层架构&#xff1f;3、描述下 TCP 连接 4 次挥手的过程&#xff1f;为什么要 4 次挥手&#xff1f;4、计算机插上电源操作系统做了什么&#xff1f;5、Linux 操作系统设备文件有哪些&#xff1f; 1、TCP 和 UDP …...

pyside/qt03——人机协同的编程教学—直接面向chatGPT实战开发(做中学,事上练)

先大概有个草图框架&#xff0c;一点点丰富 我纠结好久&#xff0c;直接用Python写UI代码 还是用designer做UI 再转Python呢&#xff0c; 因为不管怎么样都要转成Python代码&#xff0c; 想了想还是学一下designer吧&#xff0c;有个中介&#xff0c;有直观理解。 直接这样也可…...

swing快速入门(五)

注释很详细&#xff0c;直接上代码 上一篇 本篇新增内容&#xff1a; 1.布局管理器BorderLayout 2.自适应尺寸方法pack() import java.awt.*; public class swing_test_3 {public static void main(String[] args) {Frame framenew Frame("演示BorderLayout");//…...

银河麒麟v10系统SSH远程管理及切换root用户的操作方法

&#x1f4da;&#x1f4da; &#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; ​​ &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Linux》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一…...

设计模式——建造者模式(Java示例)

引言 生成器是一种创建型设计模式&#xff0c; 使你能够分步骤创建复杂对象。 与其他创建型模式不同&#xff0c; 生成器不要求产品拥有通用接口。 这使得用相同的创建过程生成不同的产品成为可能。 复杂度&#xff1a; 中等 流行度&#xff1a; 流行 使用示例&#xff1a…...

深入探索 Spring Boot:简化开发,加速部署的全方位利器

目录 导言 1. 自动配置&#xff08;Auto-Configuration&#xff09; 2. 起步依赖&#xff08;Starter Dependencies&#xff09; 3. 嵌入式 Web 服务器 4. Actuator 5. 外部化配置 6. 简化的安全性配置 7. Spring Boot CLI 8. Spring Boot DevTools 导言 在当今软件开…...

SpectralGPT: Spectral Foundation Model 论文翻译3

遥感领域的通用大模型 2023.11.13在CVPR发表 原文地址&#xff1a;[2311.07113] SpectralGPT: Spectral Foundation Model (arxiv.org) E.消融研究 在预训练阶段&#xff0c;我们对可能影响下游任务表现的各种因素进行了全面研究。这些因素包括掩蔽比、ViT patch大小、数据规…...

ubuntu-c++-可执行模块-动态链接库-链接库搜索-基础知识

文章目录 1.动态链接库简介2.动态库搜索路径3.运行时链接及搜索顺序4.查看可运行模块的链接库5.总结 1.动态链接库简介 动态库又叫动态链接库&#xff0c;是程序运行的时候加载的库&#xff0c;当动态链接库正确安装后&#xff0c;所有的程序都可以使用动态库来运行程序。动态…...

HTML中使用JavaScript实现一个简单的鼠标悬停特效。

代码中&#xff0c;我们首先在CSS中定义了一个红色的方块&#xff0c;然后使用:hover伪类定义了鼠标悬停时的样式。接着&#xff0c;在JavaScript中定义了一个函数showMessage()&#xff0c;用于在控制台输出一条消息。最后&#xff0c;在HTML中使用<div>标签定义了一个i…...

深入.NET平台和C#编程总结大全

第一章 简单认识.NET框架 &#xff08;1&#xff09;首先我们得知道 .NET框架具有两个主要组件&#xff1a;公共语言进行时CLR&#xff08;Common Language Runtime&#xff09;和框架类库FCL&#xff08;Framework Class Library&#xff09; 配图&#xff1a; &#xff08;…...

jOOQ的使用场景

jOOQ的使用场景 jOOQ最初是作为一个库完全是JDBC和所有的数据库交互的抽象层而被创建。 在已有的软件产品中经常遇到的各种最佳实践被应用到这个库中。包含如下&#xff1a; 类型安全数据库对象引用&#xff0c;通过自动生成的模式&#xff0c; 表&#xff0c; 列&#xff0c…...

Pytorch-Transformer轴承故障一维信号分类(三)

目录 前言 1 数据集制作与加载 1.1 导入数据 第一步&#xff0c;导入十分类数据 第二步&#xff0c;读取MAT文件驱动端数据 第三步&#xff0c;制作数据集 第四步&#xff0c;制作训练集和标签 1.2 数据加载&#xff0c;训练数据、测试数据分组&#xff0c;数据分batch…...

pycharm多线程报错的问题(未解决)

暂未解决&#xff01; 看了一下可能是这里的问题&#xff1a; 根据建议&#xff0c;在walks之前加了 freeze_support() 但是没有效果。 关键是&#xff0c;在jupyter上运行是没有问题的&#xff01; 未解决。...