【动态规划】通配符匹配与正则表达式匹配

news2024/12/26 13:37:37

文章目录

  • 一、通配符匹配
    • 1.1 思路分析
    • 1.2 初始化处理
    • 1.3 代码
    • 1.4 优化
  • 二、正则表达式匹配
    • 2.1 思路分析
    • 2.2 初始化设置
    • 2.3 代码

一、通配符匹配

题目描述:

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

  • ‘?’ 可以匹配任何单个字符。
  • ‘*’ 可以匹配任意字符序列(包括空字符序列)。
    判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。

示例 1:

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

示例 2:

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

示例 3:

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

1.1 思路分析

我们可以分别以i和j表示s[0~i]p[0~j]是否能成功匹配。
在这里插入图片描述
那么这里就只用讨论ij的位置,有四种情况
1️⃣ 如果s[i] == p[j],那么我们就只用判断dp[i - 1][j - 1]是否能成功匹配,如果能成功匹配,那么说明加上ij的位置也能成功匹配。
状态转移方程:dp[i][j] = s[i] == p[j] && dp[i - 1][j - 1]
2️⃣ 如果p[j] == '?'那么说明此时s[i]不管是什么都可以,只需要判断dp[i - 1][j - 1]是否能成功匹配,就跟上面一样。
状态转移方程:dp[i][j] = p[j] == '?' && dp[i - 1][j - 1]
3️⃣ 如果p[j] == '*',这里的情况就比较多,因为它可以变成0个或多个字符:
在这里插入图片描述
这么多情况只要有一种情况满足条件即可。

状态转移方程:

for(int k = 0; k <= i; k++)
{
    if(dp[i - k][j - 1])
    {
        dp[i][j] = true;
        break;
    }
}

4️⃣ 如果p[j] != '?' && p[j] != '*' && p[j] != s[i],那么说明不能匹配。

1.2 初始化处理

我们看到状态转移方程会用到i-1j- 1,所以dp表可以多开一维,而为了不改变下标的映射关系,我们可以在s串和p串的开头各自添加一个字符。
接下来就是初始化,首先dp[0][0]就代表两个空串,一定能匹配。所以dp[0][0] = true;
其次还有*在p串开头的位置出现,因为*可以变成空串,所以只要是开头的*都可以跟s[0]匹配成功:dp[0][j] = true;

1.3 代码

class Solution {
public:
    bool isMatch(string s, string p) {
        s = " " + s;
        p = " " + p;
        int n = s.size(), m = p.size();
        vector<vector<bool>> dp(n, vector<bool>(m));
        dp[0][0] = true;
        for(int j = 1; j < m; j++)
        {
            if(p[j] == '*')
            {
                dp[0][j] = true;
            }
            else break;
        }
        for(int i = 1; i < n; i++)
        {
            for(int j = 1; j < m; j++)
            {
                if((p[j] == '?' && dp[i - 1][j - 1]))
                {
                    dp[i][j] = true;
                }
                else if(s[i] == p[j] && dp[i - 1][j - 1])
                {
                    dp[i][j] = true;
                }
                else if(p[j] == '*')
                {
                    for(int k = 0; k <= i; k++)
                    {
                        if(dp[i - k][j - 1])
                        {
                            dp[i][j] = true;
                            break;
                        }
                    }
                }
            }
        }
        return dp[n - 1][m - 1];
    }
};

1.4 优化

p[j] == '*'这种情况其实可以写成:
在这里插入图片描述
而经过观察可以再写出一个式子:
在这里插入图片描述
经过观察可以发现蓝色框框圈起来的部分是相等的
在这里插入图片描述

所以可以写成:
在这里插入图片描述

class Solution {
public:
    bool isMatch(string s, string p) {
        s = " " + s;
        p = " " + p;
        int n = s.size(), m = p.size();
        vector<vector<bool>> dp(n, vector<bool>(m));
        dp[0][0] = true;
        for(int j = 1; j < m; j++)
        {
            if(p[j] == '*') dp[0][j] = true;
            else break;
        }
        for(int i = 1; i < n; i++)
        {
            for(int j = 1; j < m; j++)
            {
                if(dp[i - 1][j - 1] && (p[j] == '?' || s[i] == p[j])) dp[i][j] = true;
                else if(p[j] == '*')
                {
                    dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
                }
            }
        }
        return dp[n - 1][m - 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
解释:".
” 表示可匹配零个或多个(‘*’)任意字符(‘.’)。

这里的.字符跟上面一道题的?作用是一样的。但是*字符又区别,它的作用是把*字符的前一个字符重复0次或者多次,比方说"a*"
它可以变成:"","a","aa","aaa"……

2.1 思路分析

这里的有些情况跟上面的重复:
dp[i - 1][j - 1] && (p[j] == '.' || s[i] == p[j])的时候,dp[i][j]=true
接下来只剩p[j] == '*' 的情况:
这里要分情况讨论j的前一个元素,如果前一个元素是.,那么也就是可以变成任意的多个字符,既然要匹配多个字符,那么又是跟上面一个题一样要讨论到底变成多长。因为上面讲过优化版,所以这里直接写:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TjgwHLLy-1685717763933)(null)]

接下来如果前面一个字符是普通字符:
在这里插入图片描述
这里解释以下:空自然不用说,当只变成长度为1的字符串时,首先要判断j的前一个字符是否等于s[i],如果不相等就不用考虑前面的了。

2.2 初始化设置

还是跟上面一样多加一维,然后让dp[0][0] = true,接下来就是看p的前面全部是x*x*……这种字符串的情况:

for(int j = 2; j < m; j += 2)
{
    if(p[j] == '*') dp[0][j] = true;
    else break;
}

2.3 代码

class Solution {
public:
    bool isMatch(string s, string p) {
        s = " " + s;
        p = " " + p;
        int n = s.size(), m = p.size();
        vector<vector<bool>> dp(n, vector<bool>(m + 1));
        dp[0][0] = true;
        for(int j = 2; j < m; j += 2)
        {
            if(p[j] == '*') dp[0][j] = true;
            else break;
        }
        for(int i = 1; i < n; i++)
        {
            for(int j = 1; j < m; j++)
            {
                if(p[j] == '*')
                {
                    if(p[j - 1] == '.')
                    {
                        dp[i][j] = dp[i][j - 2] || dp[i - 1][j];
                    }
                    else
                    {
                        dp[i][j] = dp[i][j - 2] || (s[i] == p[j - 1] && dp[i - 1][j]);
                    }
                }
                else 
                {
                    dp[i][j] = dp[i - 1][j - 1] && (p[j] == '.' || s[i] == p[j]);
                }
            }
        }
        return dp[n - 1][m - 1];
    }
};

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

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

相关文章

如何在Github上免费部署网站

如何在Github上免费部署静态网站 背景一、新建仓库&#xff08;github账号的需要注册&#xff09;二、下载仓库三、将内容上传到远程仓库里四、启动Page服务 背景 部署网站需要服务器&#xff0c;但是如果你只是部署静态网站就可以蹭Github上的免费服务器。因为发现现在的过程…

基于springboot+Redis的前后端分离项目(一)-【黑马点评】

&#x1f381;&#x1f381;资源文件分享 链接&#xff1a;https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA?pwdeh11 提取码&#xff1a;eh11 基于session和redis实现登录 &#xff08;一&#xff09;前言&#xff08;二&#xff09;导入资源&#xff08;三&#xff09;短信…

Spring数据库事务处理

数据库事务的基本知识 ACID 两类丢失更新 事务回滚丢失更新&#xff1a; 目前大部分数据库已经通过锁的机制来避免了事务回滚丢失更新。 数据库锁的机制&#xff1a; 锁可以分为乐观锁和悲观锁&#xff0c;而悲观锁又分为&#xff1a;读锁(共享锁)和写锁(排它锁)&#xff0c;…

chatgpt赋能python:使用Python制作动画的步骤和工具

使用Python制作动画的步骤和工具 Python不仅是一种流行的编程语言&#xff0c;还可以用于制作动画。本文将介绍一些基本步骤和工具&#xff0c;帮助你制作出精美的动画作品。 步骤一&#xff1a;选择一个好的动画框架 Python有很多强大的动画框架可以使用。其中一些最受欢迎…

chatgpt赋能python:Python删除目录下文件:介绍和方法

Python删除目录下文件&#xff1a;介绍和方法 在日常的开发和运维工作中&#xff0c;我们可能会需要删除某个目录下的一些文件。使用Python的好处在于其强大的处理能力和简单易用的语法。本文将介绍Python删除目录下文件的方法&#xff0c;并提供一些实用的代码示例。 使用os…

java-数组和方法

java-数组和方法 一、数组 1.1 概念 数组就是存储数据长度固定的容器&#xff0c;存储多个数据的数据类型要一致。 1.2 定义格式 第一种 数据类型 [] 数组名 例: int[] arr; double[] arr; char[] arr;第二种 数据类型 数组名[] 例: int arr[]; doubl…

交流有功功率、无功功率、视在功率计算

交流有功功率、无功功率、视在功率计算 1、有功功率2、无功功率3、视在功率4、功率因数5、总结 1、有功功率 有功功率&#xff1a;在交流电路中&#xff0c;每个瞬时的有功功率是不同的&#xff0c;且不断变化&#xff0c;一般用平均有功功率&#xff08;一个周期内功率的平均…

黑盒测试用例设计练习题

1、准考证号码 对招干考试系统“输入学生成绩”子模块设计测试用例。招干考试分三个专业,准考证号第一位为专业代号&#xff0c;如&#xff1a; 1-行政专业&#xff0c; 2-法律专业&#xff0c; 3-财经专业。 行政专业准考证号码为&#xff1a;110001&#xff5e;111215 法律专…

chatgpt赋能python:Python数据清洗:如何剔除异常值

Python 数据清洗&#xff1a;如何剔除异常值 随着数据量的持续增长&#xff0c;数据清洗已经成为了数据分析中不可或缺的一个步骤。数据清洗的目的是去除错误、缺失或不必要的数据&#xff0c;从而使数据更加准确、可靠、一致和完整。本文将讲解如何使用 Python 编程语言来剔除…

【C++ 程序设计】第 2 章:面向对象的基本概念

目录 一、结构化程序设计 二、面向对象程序设计的概念和特点 &#xff08;1&#xff09;面向对象程序设计的概念 &#xff08;2&#xff09;面向对象程序设计的特点 三、类的初步知识 &#xff08;1&#xff09;类的定义 &#xff08;2&#xff09;类的定义示例 四、类…

Three.js--》实现3d踢球模型展示

目录 项目搭建 初始化three.js基础代码 设置环境纹理加载模型 使用Cannon-es实现物理世界 今天简单实现一个three.js的小Demo&#xff0c;加强自己对three知识的掌握与学习&#xff0c;只有在项目中才能灵活将所学知识运用起来&#xff0c;话不多说直接开始。 项目搭建 本…

Linux4.6LNMP架构

文章目录 计算机系统5G云计算第五章 LINUX LNMP架构一、安装 Nginx 服务1.关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下2.安装依赖包3.创建运行用户、组4.编译安装Nginx5.添加 Nginx 系统服务6.修改nginx服务配置文件 三、编译安装mysqld 服务1.将安装mysql 所需…

MySQL—存储引擎(下)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️树高千尺&#xff0c;落叶归根人生不易&…

Windows部署WSL开启pwn之旅

不用虚拟机来操作真的太爽了&#xff01;&#xff01;还有和vscode的联动&#xff0c;更是妙绝&#xff01; 目录 前言 一、WSL获取 开启WSL支持 二、各种操作 1.apt 换源 2.更新软件 3.配置SSH服务器&#xff08;对于pwn来说非必要&#xff09; 4.WSL访问windows文件 …

【ChatGPT 】国内无需注册 openai 即可访问 ChatGPT:WeTab 浏览器扩展程序的安装与使用

目录 一、Sider&#xff1a;每天免费 30 查询额度【暂不推荐】 &#xff08;1&#xff09;Edge 浏览器扩展程序&#xff1a;Sider - ChatGPT【暂不推荐】 &#xff08;2&#xff09;iOS 手机 APP&#xff1a;Sider- Al 搭档&#xff08;有需要可以安装&#xff09; 二、 We…

chatgpt赋能python:Python创建画布的教程

Python 创建画布的教程 Python是一个功能强大的编程语言&#xff0c;其中一个重要的应用是数据可视化。在数据科学、机器学习、图像处理和软件开发中&#xff0c;Python的可视化功能非常实用。本教程将介绍Python创建画布的步骤&#xff0c;以及如何使用Matplotlib创建简单的图…

生产案例:消息堆积排查分析

&#x1f4dd;作者简介&#xff1a; 大家好&#xff0c;我是CBeann&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主。 22届校招进入阿里广告部门从事Java开发工程师。 平时有空会帮大家解决问题&#xff0c;模式面试和日常答疑&#xff0c;并且提供免费云服务器使用。 有一…

2023年06月IDE流行度最新排名

点击查看最新IDE流行度最新排名&#xff08;每月更新&#xff09; 2023年06月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多&#xff0c;这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&am…

Linux4.5Nginx网站服务

文章目录 计算机系统5G云计算第五章 LINUX Nginx网站服务一、编译安装Nginx服务1.关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下2.安装依赖包3.创建运行用户、组4.编译安装Nginx5.检查、启动、重启、停止 nginx服务6.添加 Nginx 系统服务 二、认识Nginx服务的主配…

【数据结构】---几分钟简单几步学会手撕链式二叉树(下)

文章目录 前言&#x1f31f;一、二叉树链式结构的实现&#x1f30f;1.1 二叉树叶子节点个数&#x1f4ab;代码&#xff1a;&#x1f4ab;流程图&#xff1a; &#x1f30f;1.2 二叉树的高度&#x1f4ab;第一种写法(不支持)&#xff1a;&#x1f4d2;代码&#xff1a;&#x1f…