正则表达式匹配

传送门 https://leetcode-cn.com/problems/regular-expression-matching/

题目描述:

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

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

说明:

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

示例:

输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。

输入:
s = “aa”
p = “a
输出: true
解释: 因为 ‘
‘ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。

输入:
s = “ab”
p = “.
输出: true
解释: “.
“ 表示可匹配零个或多个(’*’)任意字符(’.’)。

输入:
s = “aab”
p = "c*a*b"
输出: true
解释: 因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。

输入:
s = “mississippi”
p = "mis*is*p*."
输出: false

题解:

自顶向下动态规划

推荐详细解析 https://leetcode-cn.com/problems/regular-expression-matching/solution/ji-yu-guan-fang-ti-jie-gen-xiang-xi-de-jiang-jie-b/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
enum Result{
t,f
}

Result memo[][] = null;

public boolean isMatch(String s, String p) {
memo = new Result[s.length()+1][p.length()+1];
return dp(s, p, 0, 0);
}

public boolean dp(String s, String p, int i, int j)
{
if (memo[i][j] != null)
return memo[i][j] == Result.t;

boolean ans = false;
if (j == p.length()) // 当s,p长度都为0或者相等时
{
ans = (i == s.length());
}else // j < p.length()
{
boolean first_match = (i < s.length() &&
( s.charAt(i) == p.charAt(j) || p.charAt(j) == '.' ) );
if ( p.length() > j+1 && p.charAt(j+1) == '*' )
{
ans = ( dp(s, p, i, j+2) || first_match && dp(s, p, i+1, j) );
}else
{
ans = first_match && dp(s, p, i+1, j+1);
}
}
memo[i][j] = ans? Result.t : Result.f;
return ans;
}
}

自底向上动态规划

处理方法与自顶向下相似,不过需注意数组越界问题。此外,需注意&&优先级大于||,当&&的左边为false时,程序不会执行&&的右边,所以下面程序才不会出现越界。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {

public boolean isMatch(String s, String p) {
int m = s.length(), n = p.length();
boolean[][] dp = new boolean[m+2][n+2];
dp[m][n] = true;

for (int i=m; i>=0; i--)
{
for (int j=n-1; j>=0; j--)
{
boolean first_match = i < m && s.charAt(i) == p.charAt(j) || p.charAt(j) == '.';

if (j < n-1 && p.charAt(j+1) == '*')
{
dp[i][j] = dp[i][j+2] || first_match && dp[i+1][j] ;
}else
{
dp[i][j] = first_match && dp[i+1][j+1];
}
}
}
return dp[0][0];
}
}

PS:题解来源于力扣官方题解

-------------本文结束  感谢您的阅读-------------