原题链接 https://leetcode.cn/problems/regular-expression-matching/
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
提示:
- 1 <= s.length <= 20
- 1 <= p.length <= 30
- s 只包含从 a-z 的小写字母。
- p 只包含从 a-z 的小写字母,以及字符 . 和 *。
- 保证每次出现字符 * 时,前面都匹配到有效的字符
官方的解释已经很不错了,无意间看到了英文版leetcode的一个分析总结,点这里
public boolean isMatch1(String s, String p) {
// dp[i][j]表示s的前i个字符与p的前j个字符是否匹配。
// i最大合法值是s.length;j最大合法值是p.length
boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
// 由于s,j长度都>0,所以dp[0][0]表示s的前0个字符与j的前0个字符是否匹配没有现实意义。
// 但是循环中有用到该值,且空字符串与空模式串自然是完全匹配的
dp[0][0] = true;
// pay attention, forget it when I first write
// 空字符串与任意多个 .* 都匹配
for (int j = 2; j <= p.length(); j++) {
if (p.charAt(j - 1) == '*' && dp[0][j - 2]) {
dp[0][j] = dp[0][j - 2];
}
}
for (int i = 0; i <= s.length(); i++) {
for (int j = 1; j <= p.length(); j++) {
if (p.charAt(j - 1) == s.charAt(i - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else if (p.charAt(j - 1) == '.') {
dp[i][j] = dp[i - 1][j - 1];
} else if (p.charAt(j - 1) == '*') {
if (p.charAt(j - 2) != s.charAt(i - 1) && p.charAt(j - 2) != '.') {
dp[i][j] = dp[i][j - 2];
} else {
dp[i][j] = dp[i - 1][j] || dp[i][j - 1] || dp[i][j - 2];
}
}
}
}
return dp[s.length()][p.length()];
}