正则表达式匹配
请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
动态规划解
设被匹配字符串为 s ,匹配字符串为 p 。利用一个二维数组 dp[][] 进行动态规划,dp[i][j] 表示 s 前 i 项与 p 前 j 项是否完成匹配。字符 ‘.’ 和任意单字符匹配,所以可以添加一个判定单字符是否匹配的函数,然后分匹配字符为 ‘*’ 还是普通字符讨论:
- p [ j - 1 ] == ’ * ’
d p [ i ] [ j ] = { d p [ i − 1 ] [ j ] u s e ∗ t o m a t c h d p [ i ] [ j − 2 ] n o t u s e dp[i][j]= \left\{ \begin{aligned} dp[i-1][j]~~~use~*~to~match \\ dp[i][j-2] ~~~~~~~~~~~~~~~~~not~use \end{aligned} \right. dp[i][j]={dp[i−1][j] use ∗ to matchdp[i][j−2] not use - p [ j - 1 ] 为 ’ . ’ 或普通字符
d p [ i ] [ j ] = { d p [ i − 1 ] [ j − 1 ] ( p [ j − 1 ] m a t c h e s s [ i − 1 ] ) f a l s e ( n o t m a t c h ) dp[i][j]= \left\{ \begin{aligned} dp[i-1][j-1]~~(p[j-1] ~matches~s[i-1])\\ false~~~~~~~~~~~(not~match) \end{aligned} \right. dp[i][j]={dp[i−1][j−1] (p[j−1] matches s[i−1])false (not match)
注:dp[i][j] 中 i j 表示长度,转换为 s p 的索引时需要 -1
(补充)c++ 匿名函数
官方代码写了个匿名函数,正好复习一下匿名函数的写法:
基本格式:
[capture] [parameters] {body}
[capture] 可用的形式:
[] //不截取任何变量,试图在Lambda内使用任何外部变量都是错误的(全局变量除外).
[&] //截取外部作用域中所有变量,并作为引用在函数体中使用
[=] //截取外部作用域中所有变量,并拷贝一份在函数体中使用
[=, &foo] //截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
[bar] //截取bar变量并且拷贝一份在函数体重使用,同时不截取其他变量
[this] //截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。
本题中需要截取变量 s p 引用,所以采用格式 [&]
完整代码
class Solution {
public:
bool isMatch(string s, string p) {
auto is_match = [&](int i,int j){
if(i==0){
return false;
}
if(p[j-1]=='.'){
return true;
}
return s[i-1]==p[j-1];
};
int len_s=s.length();
int len_p=p.length();
vector<vector<int>> dp(len_s+1,vector<int>(len_p+1));
dp[0][0]=1;
for(int i=0;i<=len_s;++i){
for(int j=1;j<=len_p;++j){
if(p[j-1]=='*'){
dp[i][j] |= dp[i][j-2];
if(is_match(i,j-1)){
dp[i][j] |= dp[i-1][j];
}
}else{
if(is_match(i,j)){
dp[i][j] |= dp[i-1][j-1];
}
}
}
}
return dp[len_s][len_p];
}
};