当前位置 : 首页 » 文章分类 :  算法  »  LeetCode.010.Regular Expression Matching 正则表达式匹配

LeetCode.010.Regular Expression Matching 正则表达式匹配

题目描述

10 Regular Expression Matching
https://leetcode-cn.com/problems/regular-expression-matching/

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

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

说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

示例 1:

  1. 输入:
  2. s = "aa"
  3. p = "a"
  4. 输出: false
  5. 解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

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

示例 3:

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

示例 4:

  1. 输入:
  2. s = "aab"
  3. p = "c*a*b"
  4. 输出: true
  5. 解释: 因为 '*' 表示零个或多个,这里 'c' 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"

示例 5:

  1. 输入:
  2. s = "mississippi"
  3. p = "mis*is*p*."
  4. 输出: false

相似题目

LeetCode.010.Regular Expression Matching 正则表达式匹配
LeetCode.044.Wildcard Matching 通配符匹配


解题过程

dp[i][j] 表示 s 前 i 个字符和 p 前 j 个字符是否匹配,即 s[0...i-1]p[0...j-1] 是否匹配
dp[0][0] = true 即空串和空串是匹配的,dp[s.length][p.length] 就是最终结果

1、当 p 的第 j 个字符不是 * 时,和 s 的第 i 个字符比较,相等则 dp[i][j] = dp[i-1][j-1],不等则 dp[i][j] = false
2、当 p 的第 j 个字符是 * 时,看第 p 的第 j-1 个字符,和 s 的第 i 个字符比较:
(1) 如果不等,没关系,我们可以选择不使用 p[j-1]* 这个模式(因为 * 表示重复 0 次或多次),则 dp[i][j] = dp[i][j-2]
(2) 如果相等,可以有两个选择,继续和 s 的前一个字符比较(模式重复多次),或者还是可以选择不使用 p[j-1]* 这个模式(重复 0 次),则 dp[i][j] = dp[i-1][j] || dp[i][j-2]

其中判断两个字符是否匹配时,如果 p 的字符是通配符 .,则可以和 s 中任意字符匹配。

时间复杂度 O(mn),空间复杂度 O(mn)

  1. private static class SolutionV202006 {
  2. public boolean isMatch(String s, String p) {
  3. // dp[i][j] 表示 s 前 i 个字符和 p 前 j 个字符是否匹配,即 s[0...i-1] 和 p[0...j-1] 是否匹配
  4. // 则 dp[0][0] = true, dp[s.length][p.length] 就是最终结果
  5. boolean[][] dp = new boolean[s.length() + 1][p.length() + 1]; // 默认都是 false
  6. dp[0][0] = true;
  7. // 遍历填表
  8. for (int i = 0; i <= s.length(); i++) {
  9. for (int j = 1; j <= p.length(); j++) {
  10. if (j > 0 && p.charAt(j - 1) == '*') {
  11. // s[i-1] 和 p[j-2] 匹配时, dp[i][j] = dp[i-1][j](和s前一个字符比较) || dp[i][j-2] (不使用当前的 x* 模式)
  12. if (i > 0 && match(s.charAt(i - 1), p.charAt(j - 2))) {
  13. dp[i][j] = dp[i - 1][j] || dp[i][j - 2];
  14. } else {
  15. // s[i-1] 和 p[j-2] 不匹配时,dp[i][j] = dp[i][j-2],即不使用当前的 x* 模式
  16. dp[i][j] = dp[i][j - 2];
  17. }
  18. } else {
  19. if (i > 0 && match(s.charAt(i - 1), p.charAt(j - 1))) {
  20. // s[i-1] 和 p[j-1] 匹配时, dp[i][j] = dp[i-1][j-1];否则 dp[i][j] = false
  21. dp[i][j] = dp[i - 1][j - 1];
  22. }
  23. }
  24. }
  25. }
  26. return dp[s.length()][p.length()];
  27. }
  28. // 判断字符 s 和 p 是否匹配
  29. private boolean match(char s, char p) {
  30. return p == '.' || p == s;
  31. }
  32. }

GitHub代码

algorithms/leetcode/leetcode/_010_RegularExpressionMatching.java
https://github.com/masikkk/algorithms/blob/master/leetcode/leetcode/_010_RegularExpressionMatching.java


上一篇 LeetCode.程序员面试金典.1618.Pattern Matching 模式匹配

下一篇 LeetCode.125.Valid Palindrome 验证回文串

阅读
评论
986
阅读预计4分钟
创建日期 2020-06-20
修改日期 2020-06-20
类别

页面信息

location:
protocol: http:
host: masikkk.com
hostname: masikkk.com
origin: http://masikkk.com
pathname: /article/LeetCode.010.RegularExpressionMatching/
href: http://masikkk.com/article/LeetCode.010.RegularExpressionMatching/
document:
referrer:
navigator:
platform: Linux x86_64
userAgent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)

评论