CrazyJums LeetCode and Pary For Good Job

给你一个字符串 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
解释:”.
“ 表示可匹配零个或多个(’*’)任意字符(’.’)。
示例 4:

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

输入:s = “mississippi” p = “misisp*.”
输出:false

提示:

$0 <= s.length <= 20$
$0 <= p.length <= 30$
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
保证每次出现字符 * 时,前面都匹配到有效的字符

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/regular-expression-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1 解题思路

本题可以使用动态规划来进行求解,定义$dp$数组,$dp[i][j]$表示字符串$s$的前$i$个字符和字符串$p$的前$j$的字符是否匹配。默认$dp[0][0]=true$,且$dp[m+1][n+1]$。

  • 情况1:
    $s[i-1]==p[j-1]$或者$p[j-1]==’.’$,则表示能匹配,在匹配的情况下,则只要看第$i-1$和$j-1$的匹配情况即可,即$dp[i][j]=dp[i-1][j-1]$。

  • 情况2:

    $p[j-1]=’*’$,此时表示字符串$p$之前的字符可以匹配0个、1个或者多个,分成以下几种情况

    • 子情况1:

      $s[i-1]==p[j-2]$或者$p[j-2]==’.’$,表示前一个字符可以匹配,则表示$*$号之前的字符出现了一个,则$dp[i][j]=dp[i][j-1]$。

    • 子情况2:

      $s[i-1]!=p[j-2]$时,此时$$可以匹配0个、1个或者多个$$号之前的字符,则

      $dp[i][j]=dp[i-1][j]ordp[i][j-1]ordp[i][j-2]$。

      其中$dp[i][j-2]$表示匹配0个字符,$dp[i][j-1]$表示匹配1个字符,$dp[i-1][j]$表示匹配多个字符。

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
class Solution {
public boolean isMatch(String s, String p) {
if (p == null || s == null) return false;
String s1 = " " + s; //避免比较空字符串
String p2 = " " + p;
int m = s1.length();
int n = p2.length();
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1.charAt(i - 1) == p2.charAt(j - 1) || p2.charAt(j - 1) == '.') {
dp[i][j] = dp[i - 1][j - 1];
} else if (p2.charAt(j - 1) == '*') {
if (s1.charAt(i - 1) != p2.charAt(j - 2) && p2.charAt(j - 2) != '.') {
dp[i][j] = dp[i][j - 2]; //出现0次
} else { //s.charAt(i - 1) != p.charAt(j - 2)
dp[i][j] = dp[i - 1][j] //匹配多个字符】
|| dp[i][j - 2] //匹配0个字符
|| dp[i][j - 1]; //匹配1个字符
}
}
}
}
return dp[m][n];
}
}

评论