10. 正则表达式匹配
知识点:动态规划
时间:2021年4月13日
题目链接
题目
给你一个字符串 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
解释:".” 表示可匹配零个或多个(’*’)任意字符(’.’)。
示例 4:
输入:s = “aab” p = “cab”
输出:true
解释:因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
示例 5:
输入:s = “mississippi” p = “misisp*.”
输出:false
提示:
- 0 <= s.length <= 20
- 0 <= p.length <= 30
- s 可能为空,且只包含从 a-z 的小写字母。
-p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。 - 保证每次出现字符 * 时,前面都匹配到有效的字符
解题思路
- 这是一个动态规划问题,用dp[i][j] 表示s的前i个字符是否能和p的前j个字符匹配
- 转移方程
- p[j] 是小写字母时 需要比较 s[i] 和 p[j] 相等 dp[i][j] = dp[i-1][j-1] 否则 false
- p[j] 是 . 时 dp[i][j] = dp[i-1][j-1]
- p[j] 是 * 时 当(s[i] 和 p[j-1] 相等 或者 p[j-1] = ‘.’)
- dp[i][j] = dp[i-1] [j] (匹配一个) || dp[i][j-2] (匹配0个)
- 否则 dp[i][j-2] (匹配0个)
- 注意下标 开始的地方 -1 判断
- 特殊案例 .* 和 aa、aaa 和 “” 、“a*”
代码
#include "cheader.h"
class Solution {
public:
bool isMatch(string s, string p) {
int m = s.size(), n = p.size();
vector<vector<int>> dp(m+1,vector<int>(n+1));
dp[0][0] = 1;
for(int i = 0; i <= m; i++){ //起始位置很重要 注意 "" 和 "a*"情况
for(int j = 1; j <= n; j++){
if(i > 0 && (p[j-1] == '.' || s[i-1] == p[j-1])) // 对应p是. 和 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]; //对应 一个都不匹配的情况
if(i > 0 && (s[i-1] == p[j-2] || p[j-2] == '.')) //对应和前面一个匹配 注意.* 也是可以的
dp[i][j] |= dp[i-1][j];
}else
dp[i][j] = 0; //否则为0
}
}
return dp[m][n];
}
};
int main()
{
string s("aa");
string p("aaa");
Solution S;
cout<<S.isMatch(s, p)<<endl;
return 0;
}
今天也是爱zz的一天哦!