LeetCode HOT 100 —— 10.正则表达式匹配

news2024/10/6 6:01:12

题目

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

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
在这里插入图片描述
在这里插入图片描述

思路

对于字符串p来说,可以有三种字符:

  • 普通字符:
  • '.':能够匹配s中同一位置的任意字符
  • '*' :不能单独使用,必须和前一个字符搭配使用,能够匹配s中同一位置字符任意次(包括0次,即把前面的字符消除掉)

即关键是当出现了a*这种字符的时候,到底是匹配几个a

动态规划:

  • 定义dp数组:f(i,j) 代表考虑 s 中以 i 为结尾的子串和 p 中的 j 为结尾的子串是否匹配。即最终要求的结果为 f[n][m]
  • 确定递推公式:如何求得f(i,j),这里一共分成三种情况
    (1)p[j] 为普通字符:匹配的条件是前面的字符匹配,同时 s 中的第 i 个字符和 p 中的第 j 位相同,即 f(i,j) = f(i - 1, j - 1) && s[i] == p[j]
    (2)p[j]'.':匹配的条件是前面的字符匹配, s 中的第 i 个字符可以是任意字符。即 f(i,j) = f(i - 1, j - 1) && p[j] == '.'
    (3)p[j]'*':往前读取 p[j - 1] 的字符,例如为字符 a;然后根据 a* 实际匹配 s 中 a 的个数是 0 个、1 个、2 个 …
    (3.1)当匹配为 0 个:f(i,j) = f(i, j - 2)
    (3.2)当匹配为 1 个:f(i,j) = f(i - 1, j - 2) && (s[i] == p[j - 1] || p[j - 1] == '.')
    (3.3)当匹配为 2 个:f(i,j) = f(i - 2, j - 2) && ((s[i] == p[j - 1] && s[i - 1] == p[j - 1]) || p[j - 1] == '.')

最后对于*到底匹配多少个a这个过程,对它进行一个简化过程

java代码如下:

class Solution {
    public boolean isMatch(String ss, String pp) {
        // 技巧:往原字符头部插入空格,这样得到 char 数组是从 1 开始,而且可以使得 f[0][0] = true,可以将 true 这个结果滚动下去
        int n = ss.length(), m = pp.length();
        ss = " " + ss;
        pp = " " + pp;
        char[] s = ss.toCharArray(), p = pp.toCharArray();
        // f(i,j) 代表考虑 s 中的 1~i 字符和 p 中的 1~j 字符 是否匹配
        boolean[][] f = new boolean[n + 1][m + 1];
        f[0][0] = true;
        for (int i = 0; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                // 如果下一个字符是 '*',则代表当前字符不能被单独使用,跳过
                if (j + 1 <= m && p[j + 1] == '*') continue;
                
                if (i - 1 >= 0 && p[j] != '*') {
                    // 对应了 p[j] 为普通字符和 '.' 的两种情况
                    f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
                } else if (p[j] == '*') {
                    // 对应了 p[j] 为 '*' 的情况
                    f[i][j] = (j - 2 >= 0 && f[i][j - 2]) || (i - 1 >= 0 && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.'));
                }
            }
        }
        return f[n][m];
    }
}

这里附上一个便于理解的版本:

没有降维,如果空间复杂度没有要求,这么写就行,比较好理解

class Solution {
    public boolean isMatch(String s, String p) {
        char[] cs = s.toCharArray();
        char[] cp = p.toCharArray();

        // dp[i][j]:表示s的前i个字符,p的前j个字符是否能够匹配
        boolean[][] dp = new boolean[cs.length + 1][cp.length + 1];

        // 初期值
        // s为空,p为空,能匹配上
        dp[0][0] = true;
        // p为空,s不为空,必为false(boolean数组默认值为false,无需处理)

        // s为空,p不为空,由于*可以匹配0个字符,所以有可能为true
        for (int j = 1; j <= cp.length; j++) {
            if (cp[j - 1] == '*') {
                dp[0][j] = dp[0][j - 2];
            }
        }

        // 填格子
        for (int i = 1; i <= cs.length; i++) {
            for (int j = 1; j <= cp.length; j++) {
                // 文本串和模式串末位字符能匹配上
                if (cs[i - 1] == cp[j - 1] || cp[j - 1] == '.') {
                    dp[i][j] = dp[i - 1][j - 1];
                } else if (cp[j - 1] == '*') { // 模式串末位是*
                    // 模式串*的前一个字符能够跟文本串的末位匹配上
                    if (cs[i - 1] == cp[j - 2] || cp[j - 2] == '.') {
                        dp[i][j] = dp[i][j - 2]      // *匹配0次的情况
                                || dp[i - 1][j];     // *匹配1次或多次的情况
                    } else { // 模式串*的前一个字符不能够跟文本串的末位匹配
                        dp[i][j] = dp[i][j - 2];     // *只能匹配0次
                    }
                }
            }
        }
        return dp[cs.length][cp.length];
    }
}

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

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

相关文章

11月24日国产蓝牙AOA高精度定位vs国外知名厂家的蓝牙aoa定位效果的展示

11月24日国产蓝牙AOA高精度定位vs国外知名厂家的蓝牙aoa定位效果的展示 11月24日国产蓝牙AOA高精度定位vs国外知名厂家的蓝牙aoa定位效果的展示

操作系统的基本概念

文章目录一、操作系统的概念1.什么是操作系统&#xff1f;2 计算机系统的构成3 系统软件的概念4 操作系统的主要作用二、操作系统目标和功能1. 目标1.1 有效性1.2 方便性1.3 可扩充性1.4 开放性2. 功能2.1 作为系统资源的管理者2.2 作为用户与计算机[硬件系统]之间的接口2.3 实…

Linus 文件处理(一)

目录 一、前言 二、低级文件访问 1、write 2、read 3、open 4、Initial Permissions &#xff08;1&#xff09;umask &#xff08;2&#xff09;close &#xff08;3&#xff09;ioctl &#xff08;4&#xff09;第一个 copy_system.c 程序 &#xff08;5&#xff…

Apache ShardingSphere(一) 基本概念介绍

文章目录一 基本介绍1.1 概述1.2 ShardingSphere JDBC1.3 ShardingSphere Proxy1.4 ShardingSphere Sidecar1.5 数据库的扩展1.5.1 向上扩展1.5.2 横向扩展1.5.2.1 读写分离1.5.2.2 垂直切分1.5.2.3 水平切分1.6 分库与分表1.6.1 水平分库1.6.2 水平分表1.6.3 垂直分库1.6.4 垂…

[iOS]使用MonkeyDev完成Hook

一、确定目标 先定个小目标&#xff0c;使用七猫举个例&#xff0c;去移除小说阅读页底部广告和章节之间的广告。 二、HOOK 1. 创建MonkeyApp项目导入砸壳包 2. 使用Reveal工具确定“底部广告”和“章末广告”的视图名称 底部广告 View Controller: Class: QMReader.YYReade…

Strassen矩阵乘法问题(Java)

Strassen矩阵乘法问题&#xff08;Java&#xff09; 文章目录Strassen矩阵乘法问题&#xff08;Java&#xff09;1、前置介绍3、代码实现4、复杂度分析5、参考资料1、前置介绍 矩阵乘法是线性代数中最常见的问题之一 &#xff0c;它在数值计算中有广泛的应用。 设A和B是2个nXn…

搭建灾情快速分析系统 | Bigemap助力防灾减灾重点工作

Bigemap国产基础软件凭借自身强大的新GIS引擎技术与完善的产品链&#xff0c;为相关部门提供了集"灾情采集-灾情监测-灾害快速评估-应急指挥"于一体的灾害防灾减灾解决方案&#xff0c;搭建了灾情快速分析系统&#xff0c;该系统成为相关部门应对灾情的重要支撑平台。…

虚拟号码认证如何开通?

近年来&#xff0c;经常会接到外卖、房产中介、信用贷款等电话&#xff0c;让顾客不胜其扰。现在电话标记功能使用越来越普遍&#xff0c;可以大概了解电话“来意”&#xff0c;同时也会让误标记、恶意标记很方便。对于开展业务或办公司或企业的人&#xff0c;更加不能让自己的…

排序算法之选择排序

今天来给大家介绍一下排序算法之选择排序 选择排序&#xff1a;&#xff08;Selection sort&#xff09;是一种简单直观的排序算法&#xff0c;也是一种不稳定的排序方法。 选择排序的原理&#xff1a; 一组无序待排数组&#xff0c;做升序排序&#xff0c;我们先假定第一个…

【生成模型】Diffusion Models:概率扩散模型

---前言一、Diffusion Model 基本介绍二、生成模型对比三、直观理解Diffusion model四、形式化解析Diffusion model五、详解 Diffusion Model&#xff08;数学推导&#xff09;1.前向过程(扩散过程)2.逆扩散过程3.逆扩散条件概率推导4.训练损失六、训练、测试伪代码1. 训练2.测…

鲲鹏devkit编译调试工具——《sudoku》作业解析

《sudoku》作业解析 本次实验以sudoku项目为例介绍鲲鹏编译调试插件的基本使用方法 本次实验的步骤主要为 获取源码安装鲲鹏编译调试插件服务器配置进行代码同步配置配置测试任务进行编译调试 接下来我们先获取本次实验所需要的源码 获取源码 sudoku项目已经上传到github使…

stata外部命令大全(包含面板门槛、系统GMM、空间计量、Pvar、中介效应等)

1、数据来源&#xff1a;自主整理 2、时间跨度&#xff1a;无 3、区域范围&#xff1a;无 4、指标说明&#xff1a; 该些外部命令包含面板门槛、系统GMM、空间计量、pvar、中介效应等涵盖全部 以下是部分命令截图&#xff1a; 空间计量&#xff1a; 系统GMM&#xff08;动…

Allure使用手册

一. 简介 Allure是一款支持多语言的测试结果可视化软件&#xff0c;支持Java、Python&#xff0c;搭配Junit、pytest等测试框架食用更香。本文主要讲解搭配Junit4。 二. 下载、安装部署 2.1 下载 百度搜索Allure2&#xff01;&#xff01;&#xff01; 敲重点&#xff1a;…

基于Qlearning强化学习的倒立摆控制系统matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 强化学习通常包括两个实体agent和environment。两个实体的交互如下&#xff0c;在environment的statestst下&#xff0c;agent采取actionatat进而得到rewardrtrt 并进入statest1st1。Q-l…

【头歌实验】五、Python循环结构

文章目录>>>第1关&#xff1a;达依尔的麦子数任务描述案例分析相关知识for循环测试说明参考答案>>>第2关&#xff1a;四级单词查询任务描述案例分析相关知识如何处理文件文件打开文件循环文件关闭遍历文件测试说明第3关&#xff1a;出租车车费计算任务描述案…

Monaco Editor教程(十八):使用api来完成某些键盘操作,格式化,查找,显示右侧菜单等。

背景 在一般的Web IDE中&#xff0c;我们需要将经常用到的一些操作放到顶部操作栏里&#xff0c;类似语雀的文档编辑。 代码编辑器&#xff0c;一般也会放一些查找&#xff0c;格式化&#xff0c;撤销&#xff0c;恢复。有些人喜欢用快捷键来进行这些操作&#xff0c;但由于mo…

Packet Tracer - 配置 OSPF 高级功能

地址分配表 设备 接口 IPv4 地址 子网掩码 默认网关 R1 G0/0 172.16.1.1 255.255.255.0 不适用 S0/0/0 172.16.3.1 255.255.255.252 不适用 S0/0/1 192.168.10.5 255.255.255.252 不适用 R2 G0/0 172.16.2.1 255.255.255.0 不适用 S0/0/0 172.16.3.2 …

论文笔记: 全波形反演的无监督学习: 将 CNN 与偏微分方程做成一个环

摘要: 分享对论文的理解, 原文见 Peng Jin, Xitong Zhang, Yinpeng Chen, Sharon Xiaolei Huang, Zicheng Liu, Youzuo Lin, Unsupervised learning of full-waveform inversion: connecting CNN and partial differential equation in a loop. 论文发表于计算机方面的顶会 ICL…

(续)SSM整合之SSM整合笔记(Spring整合MyBatis)(P179-188)

一 准备工作 1 新建模块ssm com.atguigu.ssm 2 导入依赖 <packaging>war</packaging><properties><spring.version>5.3.1</spring.version> </properties><dependencies><dependency><groupId>org.springframewo…

Linux:进程(二)

文章目录前言一、环境变量1.概念2.常见环境变量3.一个疑问4.通过系统调用获取或设置环境变量二、地址空间1.引入2.分页&进程地址空间1.页表2.写时拷贝3.为什么要有地址空间总结前言 今天我们继续学习进程相关知识。 一、环境变量 1.概念 环境变量(environment variables)…