【刷题记录】10. 正则表达式匹配

简介: 【刷题记录】10. 正则表达式匹配

一、题目描述


来源:力扣(LeetCode)


给你一个字符串 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 <= 30
  • s 只包含从 a-z 的小写字母。
  • p 只包含从 a-z 的小写字母,以及字符 . 和 *。
    **保证每次出现字符 时,前面都匹配到有效的字符


二、思路分析


这个题目我可以利用动态规划的思想来解决:


  • 首先我们定义dp[i][j] 表示 s 的前 i 个是否能被 p 的前 j 个匹配
  • 如果 p 的第 j 个字符是一个字母
  • 如果 s 的第 i 个字符与 p 的第 j 个字符不相同,那么无法进行匹配,不符合了。
  • 如果前面的都匹配的同时,且  s 的第 i 个字符与 p 的第 j 个字符相同,即 dp[i-1][j-1] = dp[i,j] && s[i]=p[j]
  • 如果 p 的第 j 个字符是 *, 那么我们就是对 前面一个字符p[j-1]就行任意次数的匹配
  • 0 次就是 dp[i][j] == dp[i][j-2]
  • 1 次就是 dp[i][j] == dp[i−1][j−2] && s[i] == p[j-1]
  • 2 次就是 dp[i][j] == dp[i−2][j−2] && s[i-1]s[i] == p[j-1]
  • ....
    总结就是

网络异常,图片无法展示
|

  • 如果  p[j]'.':匹配的条件是前面的字符匹配, s 中的第 i 个字符可以是任意字符。即 dp[i,j] = dp[i - 1, j - 1] && p[j] == '.'
  • 动态规划的边界条件为
    网络异常,图片无法展示
    |
    ,即两个空字符串是可以匹配的。最终的答案即为
    网络异常,图片无法展示
    |
    ,其中 mn 分别是字符串 sp 的长度


三、代码实现

class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();
        //dp[i][j] s 中的 1~i 字符 和 p 中的 1~j 字符 是否匹配
        boolean[][] dp = new boolean[m +1][n +1];
        dp[0][0] =true;
for (int i =0; i <= m; ++i) {
for (int j =1; j <= n; ++j) {
if (p.charAt(j -1) =='*') {
                    dp[i][j] = dp[i][j -2];
if (matches(s, p, i, j -1)) {
                        dp[i][j] = dp[i][j] || dp[i -1][j];
                    }
                } else {
if (matches(s, p, i, j)) {
                        dp[i][j] = dp[i -1][j -1];
                    }
                }
            }
        }
        return dp[m][n];
    }
    public boolean matches(String s, String p, int i, int j) {
if (i ==0) {
            return false;
        }
if (p.charAt(j -1) =='.') {
            return true;
        }
        return s.charAt(i -1) == p.charAt(j -1);
    }
 }


复杂度分析


复杂度分析


  • 时间复杂度:
    网络异常,图片无法展示
    |
    ,其中 mn 分别是字符串 sp 的长度,每个状态在进行转移时的时间复杂度为
    网络异常,图片无法展示
    |
  • 空间复杂度:
    网络异常,图片无法展示
    |
    ,存储所有状态使用的空间。


运行结果


网络异常,图片无法展示
|


总结


这道题的重点是 动态规划 的运用


而动态规划的解题核心主要分为两步:


  1. 第一步:状态的定义
  2. 第二步:状态转移方程的定义


状态表示的是我们在求解问题之中,对问题的分析和转化


运用动态规划我们将一个大问题转化成几个小问题,求解小问题,然后推出大问题的解

目录
相关文章
markdown常用语法--花括号(超详细)
markdown常用语法--花括号(超详细)
|
3月前
|
机器学习/深度学习 人工智能 搜索推荐
Deep Search 如何理解业务仓库代码?
本文系统地介绍了 Deep Search 和 Deep Research 的概念、与传统 RAG 的区别、当前主流的商业产品与开源方案、在代码领域的应用(如 Deep Search for 仓库问答)以及未来的发展规划。
367 21
Deep Search 如何理解业务仓库代码?
|
8月前
|
人工智能 安全 API
最近谈论 SSE 和 WebSocket 的人越来越多的原因
实时通信已经成了大模型应用的标配。
1113 241
最近谈论 SSE 和 WebSocket 的人越来越多的原因
|
人工智能 Java API
Spring AI 抢先体验,5 分钟玩转 Java AI 应用开发
Spring Cloud Alibaba AI 以 Spring AI 为基础,并在此基础上提供阿里云通义系列大模型全面适配,让用户在 5 分钟内开发基于通义大模型的 Java AI 应用。
227230 109
|
6月前
|
人工智能 机器人 API
一周AI大事件
一周AI大事件
|
10月前
|
Java 程序员 API
Java循环操作哪个快?
本文探讨了Java中Stream API与传统for循环的性能对比及适用场景。作者通过实际案例分析,指出在某些情况下,过度使用Stream API会导致代码可读性和维护性下降。测试结果显示,在数据量较小的情况下,普通for循环的性能优于Stream API,尤其是在涉及多次类似操作时。因此,建议在开发中根据具体需求选择合适的遍历方式,以提高代码的可读性和性能。
226 5
Java循环操作哪个快?
|
缓存 前端开发 rax
测试cache访问延迟背后的计算机原理
CPU的cache往往是分多级的金字塔模型,如何在多级cache中测试cache的延迟?
1528 2
测试cache访问延迟背后的计算机原理
|
存储 Prometheus 监控
Prometheus 存储方案与优化
【8月更文第29天】Prometheus 是一个流行的开源监控系统,它使用时间序列数据库来存储监控数据。Prometheus 的时间序列数据库是基于本地文件系统的,这种设计提供了高吞吐量的读写能力,但同时也带来了存储方面的挑战。本文将详细介绍 Prometheus 存储的工作原理,并提出一些优化策略以减少磁盘占用。
1087 2
|
人工智能 自然语言处理 数据安全/隐私保护
扣子(Coze)搭建一个AI智能体
扣子(Coze)搭建一个AI智能体
3799 2
|
自然语言处理 达摩院 搜索推荐
阿里推出文本搜索排序新技术,登顶国际权威NLP榜单MS MARCO
3月28日,阿里巴巴团队以0.450的得分,刷新了国际权威自然语言处理(NLP)榜单MS MARCO短文本检索排序任务历史纪录。据悉,搜索团队最新研发的文本检索及排序技术已通过阿里云智能开放搜索OpenSearch产品对外输出。
1369 0
阿里推出文本搜索排序新技术,登顶国际权威NLP榜单MS MARCO

热门文章

最新文章