写点什么

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

作者:WangNing
  • 2022 年 7 月 14 日
  • 本文字数:1593 字

    阅读完需:约 5 分钟

一、题目描述

来源:力扣(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]

  • ....总结就是 $dp[i,j]=\begin{cases}dp[i][j-2] ,when & s[i] \neq p[j-1] \dp[i−1][j] or dp[i][j−2],when & s[i]==p[j−1] \\end{cases}$

  • 如果 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. 第二步:状态转移方程的定义


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


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

发布于: 刚刚阅读数: 5
用户头像

WangNing

关注

还未添加个人签名 2020.10.13 加入

一个只想提(快)升(乐)自(摸)我(鱼)的混子选手~

评论

发布
暂无评论
【刷题记录】10. 正则表达式匹配_7月月更_WangNing_InfoQ写作社区