题目描述
给你一个字符串 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解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
提示:
- 1 <= s.length <= 20
 - 1 <= p.length <= 30
 - s 只包含从 a-z 的小写字母。
 - p 只包含从 a-z 的小写字母,以及字符 . 和 *。
 - 保证每次出现字符 * 时,前面都匹配到有效的字符
个人解法
 
Java(递归)
public static boolean isMatch(String s, String p) {int pl=p.length(),sl=s.length();//如果p长为0,s不为0肯定无法匹配(s=“a”,p=“”)if (pl == 0) {return sl == 0;}//存储判断第一个字符是否可能相等的结果//①s="a",p="a" ②s="a",p="." 这两种情况都相等boolean result = (sl != 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'));if (pl>=2&&p.charAt(1)=='*') {//s="aaabc",p="a*abc"//左=>新s="aaabc",新p="abc“假设a*代表0个字符//右=>新s="aabc",新p="a*abc"假设从s中取出一个a(可能和p中不一样,那就是false)消掉return isMatch(s,p.substring(2))||(result&&isMatch(s.substring(1),p));}else {//s[0]=p[0]&&sl=1&&pl=1 s="a",p="a"//s[0]=p[0]&&p[1]!="*" s="ab",p="ab*"相当于判断s="b",p="b*"//s[0]!=p[0]&&p[1]!="*" s="ab",p="bb*" 结果为falsereturn result&&isMatch(s.substring(1),p.substring(1));}}
JavaScript
/*** @param {string} s* @param {string} p* @return {boolean}*/var isMatch = function (s, p) {if (p.length === 0) {return s.length === 0;}const result = s.length !== 0 && (s[0] === p[0] || p[0] === '.');if (p.length >= 2 && p[1] === '*') {return isMatch(s, p.substring(2)) || (result && isMatch(s.substring(1), p));} else {return result && isMatch(s.substring(1), p.substring(1));}};
更优解法
Java(动态规划)

消掉一个a的情况可分解为消掉多个a的第一步以及剩下去消掉0个
class Solution {public boolean isMatch(String s, String p) {int m = s.length();int n = p.length();boolean[][] f = new boolean[m + 1][n + 1];f[0][0] = true;for (int i = 0; i <= m; ++i) {for (int j = 1; j <= n; ++j) {//如果p(j-1)等于"*"if (p.charAt(j - 1) == '*') {//s消掉0个相同字符f[i][j] = f[i][j - 2];//s消掉一个相同字符或其他情况if (matches(s, p, i, j - 1)) {f[i][j] = f[i][j] || f[i - 1][j];}} else {//如果p(j-1)≠"*"if (matches(s, p, i, j)) {f[i][j] = f[i - 1][j - 1];}}}}return f[m][n];}public boolean matches(String s, String p, int i, int j) {if (i == 0) {return false;}if (p.charAt(j - 1) == '.') {return true;}return s.charAt(i - 1) == p.charAt(j - 1);}}
JavaScript
let isMatch = function (s, p) {let dp = Array(s.length + 1);for (let i = 0; i < dp.length; i++) {dp[i] = Array(p.length + 1).fill(false)}dp[0][0] = true;for (let i = 1; i < p.length; i++) {if (p.charAt(i) === "*") {dp[0][i + 1] = dp[0][i - 1]}}for (let i = 0; i < s.length; i++) {for (let j = 0; j < p.length; j++) {if (p.charAt(j) === '.') {dp[i + 1][j + 1] = dp[i][j]}if (p.charAt(j) === s.charAt(i)) {dp[i + 1][j + 1] = dp[i][j]}if (p.charAt(j) === '*') {if (p.charAt(j - 1) !== s.charAt(i) && p.charAt(j - 1) !== '.') {dp[i + 1][j + 1] = dp[i + 1][j - 1]} else {dp[i + 1][j + 1] = (dp[i + 1][j] || dp[i][j + 1] || dp[i + 1][j - 1])}}}}return dp[s.length][p.length]};
