问题:
Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
给你一个字符串 s
和一个字符规律 p
,请你来实现一个支持 '.'
和 '*'
的正则表达式匹配。
分析:
其实这题没什么特殊的思路,很典型的动态规划题,只要不同情况考虑得全面即可
代码:
/**
* 正则表达式匹配
* Regular Expression Matching
*
* @author DongWei
* @version 2019/6/19
*/
class Solution {
public boolean isMatch(String s, String p) {
// 动态规划准备,match[i][j] 表示 s 的 0 到 i-1 位和 p 的 0 到 j-1 位是否可以匹配
boolean[][] match = new boolean[s.length() + 1][p.length() + 1];
char[] ss = s.toCharArray();
char[] ps = p.toCharArray();
// 初始化,p 开头的 * 可以跳过匹配
match[0][0] = true;
int idx = 1;
while (idx < ps.length && ps[idx] == '*') {
match[0][idx + 1] = true;
idx += 2;
}
// 动态规划
for (int i = 0; i < ss.length; i ++) {
for (int j = 0; j < ps.length; j ++) {
char a = ss[i];
char b = ps[j];
// 如果 pattern 的这一位为'.',无论是什么字符都可以匹配成功
if (b == '.') {
match[i + 1][j + 1] = match[i][j];
} else if (b == '*') {
// 如果 pattern 的这一位为'*'
if (a == p.charAt(j - 1) || ps[j - 1] == '.') {
// 如果字符串的这一位和 * 前的字符匹配(字符相等或 pattern 前一位是'.'
// 考虑两种情况,第一种是与 * 匹配,第二种是跳过 * 匹配
// 与 * 匹配,又可以分为两种情况,前面的字符串匹配到了 * 或没有,分别是 match[i][j - 1] 和 match[i][j + 1]
// 但是在 p[j] 为 * 的情况下,match[i][j - 1] 为 true 的时候 match[i][j+1] 必然为 true
// 因此省略 match[i][j - 1]
match[i + 1][j + 1] = match[i][j + 1] | match[i + 1][j - 1];
} else {
// 如果字符串的这一位和 * 前的字符不匹配,只能跳过 * 的匹配
match[i + 1][j + 1] = match[i + 1][j - 1];
}
} else {
// 如果 pattern 的这一位为普通字符,根据字符是否相等判断是否匹配
if (a == b) {
match[i + 1][j + 1] = match[i][j];
} else {
match[i + 1][j + 1] = false;
}
}
}
}
// 返回匹配结果
return match[ss.length][ps.length];
}
}
运行速度5ms~10ms