10. Regular Expression Matching

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
class Solution {
public boolean isMatch(String s, String p) {
// 定义 dp[i][j] 为 s 前 i 个字符与 p 前 j 个字符是否匹配
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];

// 当 p 为空时,仅当 s 为空才能匹配
dp[0][0] = true;
// 当 s 为空时,可能与 'a*', 'a*a*' 等字符规律匹配
for (int j = 2; j <= p.length() && p.charAt(j - 1) == '*'; j += 2) {
dp[0][j] = true;
}

for (int i = 1; i <= s.length(); i++) {
for (int j = 1; j <= p.length(); j++) {
char sc = s.charAt(i - 1);
char pc = p.charAt(j - 1);
if (pc == '.') {
dp[i][j] = dp[i - 1][j - 1];
} else if (pc == '*') {
char pre = p.charAt(j - 2);
// 匹配 0 次
dp[i][j] = dp[i][j - 2]; // 注意此处是 j - 2, '*' 及前一个字符都需要消除
// 匹配 1 次
dp[i][j] |= dp[i - 1][j - 1] && (pre == '.' || sc == pre);
// 匹配多次
dp[i][j] |= dp[i - 1][j] && (pre == '.' || sc == pre);
} else {
// pc is alpha
dp[i][j] = dp[i - 1][j - 1] && sc == pc;
}
}
}

return dp[s.length()][p.length()];
}
}

注意 * 匹配 0 次时需要将 * 前面的字符消除。

References

10. Regular Expression Matching
剑指 Offer 19. 正则表达式匹配
逐行详细讲解,由浅入深,dp和递归两种思路