请实现一个函数用来匹配包含'. '和''的正则表达式。模式中的字符'.'表示任意一个字符,而''表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/zh… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1. 思考
假设待匹配的字符串为s,匹配模式为p。dp[i][j]表示s的前i个字符和p的前j个字符能否匹配。从最简单的情况考虑:
1). 假设模式p中不存在'*',则直接逐字符匹配。即
2). 假设模式p中存在'*',需要考虑'*'匹配几次,
- 匹配0次,相当于直接去掉匹配模式p中最后两个字符
- 匹配1次,相当于s的最后一个字符与匹配模式p的最后两个字符匹配
- 匹配2次,相当于s的最后两个字符与匹配模式p的最后两个字符匹配 dp[i][j]=dp[i-2][j-2] 综上所述,匹配1次或多次的时候可以理解为先匹配一次,模式保留,否则枚举所有可能无端增加时间复杂度,并且不利于代码编写。 因此可以分成去掉和保留匹配模式两种情况如下
因此考虑上述两种情况可得到如下公式:
2 Coding
bool isMatch(string s, string p)
{
int m = s.size(), n = p.size();
vector<vector<bool>> dp(m+1, vector<bool>(n+1, false));
dp[0][0] = true; // i = 0, j = 0, 匹配
for (int j = 1; j < n + 1; ++j) // i = 0, j != 0, 根据匹配模式可能匹配如模式'.*','*'匹配0个时匹配
{
if (p[j - 1] == '*')
dp[0][j] = dp[0][j - 2];
}
//j = 0, i != 0时,不匹配
for (int i = 1; i < m + 1; ++i)
{
for (int j = 1; j < n + 1; ++j)
{
if (p[j - 1] != '*') //情况1
dp[i][j] = dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
else //情况2
{
dp[i][j] = dp[i][j] || dp[i][j - 2];
if(s[i - 1] == p[j - 2] || p[j - 2] == '.')
dp[i][j] = dp[i][j] || dp[i - 1][j];
}
}
}
return dp[m][n];
}