Link:
题目要求
给你一个字符串s和一个字符规律p,请你来实现一个支持'.'和'*'的正则表达式匹配。
'.'匹配任意单个字符
'*'匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串s的,而不是部分字符串。
核心算法和原理
- 子序列问题容易想到dp
- dp数组定义:dp[i][j] 表示 s[..i - 1] 与 p [..j - 1]是否匹配,i = 0或j = 0表示匹配无字符的情况
- 状态转移:分j == ‘*’, ‘.’和普通字符的情况
- 普通字符 / ‘.’:相等则dp[i][j] = dp[i - 1][j - 1]
- ‘*’:根据匹配个数不同来确定:
- 匹配0个:dp[i][j - 2]
- 匹配一个或多个:如果s[i - 1] == p[j - 2] || p[j - 2] == ‘.’(也就是星号前面那个)则dp[i - 1][j]
- 其他情况都为false
- 初始化:dp[0][0] = true,同时注意如果p的开头存在匹配0个字符的情况则dp[0][j] = true
- e.g. a*c*b
- 拓展:如果还有’?’ (匹配0或1个),则和*类似,不匹配多个即 = dp[i][j - 2] || dp[i][j - 1]
代码
class Solution { public: bool isMatch(string s, string p) { int m = s.size(), n = p.size(); vector dp(m + 1, vector<bool>(n + 1, false)); dp[0][0] = true; for (int j = 2; j <= n && p[j - 1] == '*'; j += 2) { dp[0][j] = true; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (p[j - 1] == s[i - 1] || p[j - 1] == '.') { dp[i][j] = dp[i - 1][j - 1]; } else if (p[j - 1] == '*') { dp[i][j] = dp[i][j - 2] || (dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.')); } } } return dp[m][n]; } };
