10. 正则表达式匹配
题目描述
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,完全匹配).
The function prototype(函数原型) should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
方法1
思路
递归解决方案
这个递推是从左向右进行,要考虑正则表达式的解码规则
代码实现
class Solution {
public:
bool isMatch(const char *s, const char *p) {
if(*s=='\0' && *p=='\0')
return true;
if(*p=='\0')
return false;
//正是有了上面的判断,下面的是*(p)不为空时的情况
//*和它前面的字符应该作为一个整体进行解码,不能单独解码
if(*(p+1)=='*')
{
if(*s!='\0' && (*p=='.' || *p==*s))
//大于1次 1次 0次
return isMatch(s+1,p) || isMatch(s+1,p+2) || isMatch(s,p+2);
else
return isMatch(s,p+2);//这个方向时s可以为空
}
else if(*s!='\0' && (*p=='.' || *p==*s))
return isMatch(s+1,p+1);
else return false;
}
};
方法2
思路
动态规划求解:dp[i][j]
代表s{0...i-1}
和p{0...j-1}
是否完全匹配,dp[i][j]
的含义,可以根据动态规划第一步操作后,之后需要解决的子问题来设计.
代码实现
class Solution {
public:
bool isMatch(string s, string p) {
int slen = s.length();
int plen = p.length();
if(slen==0 && plen==0)
return true;
if(slen!=0 && plen==0)
return false;
//为了递推公式的方便,我们需要人为的创造长度为0时的情况,
//所以这里的dp用的是长度而不是下标
vector<vector<bool>> dp(slen+1,vector<bool>(plen+1,false));
dp[0][0] = true;
for(int i = 2; i<=plen; i++)
{
if(p[i-1]=='*')
dp[0][i] = dp[0][i-2];
}//根据我们对dp的初始化情况dp[i][0]=false,1<=i<=slen天然的已经计算出正确的值了
for(int i = 1; i <= slen; i++)
{
for(int j = 1; j <= plen; j++)
{
if(p[j-1]==s[i-1] || p[j-1] == '.')
dp[i][j] = dp[i-1][j-1];
else if(j>1 && p[j-1] == '*')//如果要使用*匹配时*前面必须得有字符
{
if(p[j-2]!=s[i-1] && p[j-2] != '.')
dp[i][j]=dp[i][j-2];//0次
else //多于1次 1次 0次
dp[i][j]=dp[i-1][j] || dp[i-1][j-2] || dp[i][j-2];
//dp[i][j]=dp[i-1][j] || dp[i][j-2];
} //dp[i-1][j]包括dp[i-1][j-2]的情况,dp[i-1][j-2]成功,dp[i-1][j]一定成功
}
}
return dp[slen][plen];
}
};