10. Regular Expression Matching

Dynamic Programming

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
class Solution {
public boolean isMatch(String s, String p) {
int m = s.length(), n = p.length();
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;

// Handle patterns like a*, a*b*, a*b*c* that can match an empty string
for (int j = 2; j <= n; j += 2) {
if (p.charAt(j - 1) == '*' && dp[0][j - 2]) {
dp[0][j] = true;
}
}

for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
char sc = s.charAt(i - 1);
char pc = p.charAt(j - 1);

if (pc == sc || pc == '.') {
dp[i][j] = dp[i - 1][j - 1];
} else if (pc == '*') {
char prev = p.charAt(j - 2);
dp[i][j] = dp[i][j - 2]; // zero occurrence
if (prev == '.' || prev == sc) {
dp[i][j] |= dp[i - 1][j]; // one or more
}
}
}
}

return dp[m][n];
}
}

Remarks:

  1. Use DP to reduce calculation

  2. Two situations of handling *:

    a. no occurrence so the current two patterns can be skipped (ab* - > a when there’s no b)

    b. one or more times: the current * will absorb the last string char, and check the previous one dp[i][j] -> dp[i-1][j], while the position/length of the current pattern keeps unchanged