LEETCODE专题
10. Regular Expression Matching
首先我們先來看一下題目要求:
这里先要讲讲题目的要求。
这里题目要求需要来个分类讨论,一个大类是p中’‘字符, 另一个大类是p中的非’‘字符。这里需要进行一个条件判断。这也是这道题的一个大坑。
如果单单从条件判断来进行,就要考虑很多种情况,测试的输入比样例的输入要复杂得多,多样得多。譬如s=”aaa”, p=”a*ab*c*”; s=”aacccbbaabb”, p=”.aabb”。这样就要考虑非’‘字符优先匹配。刚开始笔者陷入这个坑中的时候甚至还想过开两个队列来存储非’‘字符和’‘,以便分开匹配。但是这一条路走到黑,也的确就是黑了。
后来学了动态规划之后发现其实这个问题是有最优子结构的,也就是说两个字符串的前缀就是这个问题的子问题。
参照背包问题的动态规划解法,我们可以新建一个二维数组,如m[x][y]来记录两个字串的匹配与否。例如,m[0][0]表示取s的0个字符,p的0个字符来进行匹配,匹配结果为true;m[2][3]表示取s的2个字符,p的3个字符进行匹配。
接下来就是分类的处理:
- 不带’*’的字符匹配:直接匹配当前的s字符和p字符
带’*’的字符匹配:若s当前字符与p的上一个字符不匹配,则两个字符串仍然能够匹配的可能就是p的带’*’字符和p的上一个字符的组成字符串匹配数为0;如果s当前字符与p的上一个字符匹配,则两个字符串能够匹配的可能就是s的上一个字符和p的带’*’字符及上一个字符的组成字符串匹配,或者我们可以选择不匹配。
这里注意下,能够匹配并不仅仅意味着两个字符一模一样,也有可能p的当前字符为’.’,能够匹配任何字符。
下面直接上代码:
class Solution {
public:
bool isMatch(string s, string p) {
/**
* This problem is a typical knapsack
* of prefix, we can then set the 2-D
* bool matrix for matched.
* m[i][j] stands for
* s[0, 1..i - 1]
* is matched with
* p[0, 1..j - 1]
*
* Also, there are 2 situations we can
* tell if they are matched;
* 1. p[j - 1] != '*', then
* (m[i - 1][j - 1] &&
* (s[i - 1] == p[j - 1] ||
* p[j - 1] == '.') ) must be TRUE
* OR
* 2. p[j - 1] == '*', then
* a.if p[j - 2] cannot be matched,
* m[i][j - 2] must be TRUE
* OR
* b.if p[j - 2] can be matched
* (p[j - 2] can be '.'), then
* (s[i - 1] == p[j - 2] ||
* p[j - 2] == '.') &&
* m[i - 1][j] must be TRUE
**/
// firstly, check if both of them are empty
if (s.empty() && p.empty()) return true;
else if (p.empty()) return false;
int iend = s.size() + 1;
int jend = p.size() + 1;
int i, j;
vector<vector<bool> > m(iend, vector<bool>(jend, false));
m[0][0] = true;
for (j = 1; j < jend; j++) {
m[0][j] = (j > 1 && p[j - 1] == '*' && m[0][j - 2]);
}
for (i = 1; i < iend; i++) {
m[i][0] = false;
}
// matching begins
for (i = 1; i < iend; i++) {
for (j = 1; j < jend; j++) {
if (p[j - 1] != '*') {
m[i][j] = m[i - 1][j - 1] &&
(s[i - 1] == p[j - 1] || p[j - 1] == '.');
} else if (j > 1) {
if (p[j - 2] != s[i - 1] && p[j - 2] != '.') {
m[i][j] = m[i][j - 2];
} else {
m[i][j] = (m[i - 1][j] || m[i][j - 2]);
}
} else {
m[i][j] = false;
}
}
}
return m[iend - 1][jend - 1];
}
};
时间复杂度:O(n^2)