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:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: 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)
private static class SolutionV202006 {
public boolean isMatch(String s, String p) {
// dp[i][j] 表示 s 前 i 个字符和 p 前 j 个字符是否匹配,即 s[0...i-1] 和 p[0...j-1] 是否匹配
// 则 dp[0][0] = true, dp[s.length][p.length] 就是最终结果
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1]; // 默认都是 false
dp[0][0] = true;
// 遍历填表
for (int i = 0; i <= s.length(); i++) {
for (int j = 1; j <= p.length(); j++) {
if (j > 0 && p.charAt(j - 1) == '*') {
// s[i-1] 和 p[j-2] 匹配时, dp[i][j] = dp[i-1][j](和s前一个字符比较) || dp[i][j-2] (不使用当前的 x* 模式)
if (i > 0 && match(s.charAt(i - 1), p.charAt(j - 2))) {
dp[i][j] = dp[i - 1][j] || dp[i][j - 2];
} else {
// s[i-1] 和 p[j-2] 不匹配时,dp[i][j] = dp[i][j-2],即不使用当前的 x* 模式
dp[i][j] = dp[i][j - 2];
}
} else {
if (i > 0 && match(s.charAt(i - 1), p.charAt(j - 1))) {
// s[i-1] 和 p[j-1] 匹配时, dp[i][j] = dp[i-1][j-1];否则 dp[i][j] = false
dp[i][j] = dp[i - 1][j - 1];
}
}
}
}
return dp[s.length()][p.length()];
}
// 判断字符 s 和 p 是否匹配
private boolean match(char s, char p) {
return p == '.' || p == s;
}
}
GitHub代码
algorithms/leetcode/leetcode/_010_RegularExpressionMatching.java
https://github.com/masikkk/algorithms/blob/master/leetcode/leetcode/_010_RegularExpressionMatching.java
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: