Given an input string (s
) and a pattern (p
), implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character. '*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like.
or*
.
Example 1:
Input: s = "aa" p = "a" Output: false Explanation: "a" does not match the entire string "aa".
Example 2:
Input: s = "aa" p = "a*" Output: true Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
Input: s = "ab" p = ".*" Output: true Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:
Input: s = "aab" p = "c*a*b" Output: true Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".
Example 5:
Input: s = "mississippi" p = "mis*is*p*." Output: false
解答:
1. 回溯(递归):分为从左到右和从右到左两种,这里只记录从左到右。
判读p[j+1]是否是"*":如果不是,则必须要保证s[i]和p[j]能匹配,即相等或".";如果是,则先判断消掉前面字符是否可行,再 继续判断不消除时,遇到重复字符s+1。代码如下:
class Solution {
public:
bool isMatch(string s, string p) {
return match(s,0,p,0);
}
bool match(string s, int i, string p, int j)
{
if(j==p.size()) if(i==s.size()) return true; // recursion base
if(p[j+1]!='*')
{
if(i<s.size()&&(p[j]=='.'||p[j]==s[i])) if(match(s,i+1,p,j+1)) return true;
}
else if(p[j+1]=='*')
{
if(match(s,i,p,j+2)) return true;
while(i<s.size()&&(p[j]=='.'||s[i]==p[j]))
{
if(match(s,i+1,p,j+2)) return true;
i++;
}
}
return false;// recursion base
}
};
2. 动态规划:
/*
动态规划版本,类似于递归版本的从右向左,自底向上传播true值,默认false
dp[i][j] means string s with len i matches string p with length j
核心思想:与递归是一模一样的,
1.先判断当前patern字符是否是'*'?
(1)不是:则必须s与p的当前字符匹配(直接相等或通配符),才能把dp[i-1][j-1]的可能真值传过来
(2)是:分两种情况,a). 跳过前面字符,接收dp[i][j-2]的值 b). p的前一字符与s的当前字符能匹配,那么可传递dp[i-1][j]的值
程序过程:先给定边界条件,再自低向上递推;
*/
class Solution {
public:
bool isMatch(string s, string p) {
int i,j;
bool dp[s.size()+1][p.size()+1] = {false}; //len 0 ~ len s.size(), so s.size()+1
//boundary condition
dp[0][0] = true;
for(i=1;i<=p.size();i++)
{
dp[0][i] = (p[i-1]=='*' && dp[0][i-2]);
}
//对于平凡情形,有可能传播true值的情形
for(i=1;i<=s.size();i++) //注意边界与等号
for(j=1;j<=p.size();j++)
{
if(p[j-1]!='*')
{
dp[i][j] = dp[i-1][j-1] && (s[i-1]==p[j-1]||p[j-1]=='.');
}
else
{
dp[i][j] = dp[i][j-2] || ((p[j-2]==s[i-1]||p[j-2]=='.') && dp[i-1][j]);
}
}
return dp[s.size()][p.size()];
}
};