#LeetCode 10. Regular Expression Matching
本博客参考:http://www.cnblogs.com/grandyang/p/4461713.html
详细解析见另一题:【重点】剑指offer——面试题53:正则表达式匹配里面的代码风格是C的,现在把它改成C++风格的代码。在剑指offer53题的代码中,由于代码风格的原因,未考虑p.size() == 1的情况,这里也做了适当修改
##Solution1:递归
代码中的注释写的不是太清楚,加一点:
一、当模式中的第二个字符不是“”时:
1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的。
2、如果字符串第一个字符和模式中的第一个字符相不匹配,直接返回false。
二、当模式中的第二个字符是“”时:
如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:
1、x匹配0个字符。模式后移2字符,相当于x被忽略;(一开始忘了即使当前字符匹配,也存在忽略掉的情况!!!)
2、x匹配1个字符。字符串后移1字符,模式后移2字符;
3、x匹配多于1个字符。字符串后移1字符,模式不变,即继续匹配字符下一位,因为*可以匹配多位;
注意:情况2可以被情况1和情况3包含。执行一次情况3,再执行一次情况1,就相当于情况2。
class Solution {
public:
bool isMatch(string s, string p) {
if (p.empty()) return s.empty();
if (p.size() == 1) {
return (s.size() == 1 && (s[0] == p[0] || p[0] == '.'));
}
//if the next character in pattern is not '*'
if (p[1] != '*') {
//第一个条件没有判断s.size()是否为0,看似有溢出的可能
//实际上此处另有玄妙,见下面分解!
if (s[0] == p[0] || (!s.empty() && p[0] == '.'))
return isMatch(s.substr(1), p.substr(1));
else
return false;
}
//if the next character is '*'
else {
if (s[0] == p[0] || (!s.empty() && p[0] == '.'))
return isMatch(s, p.substr(2)) || isMatch(s.substr(1), p);
//刚开始一直不懂为何要返回match(str, pattern+2)的值,原因在于'*'可以匹配0个字符
//即使是当前字符匹配,也存在匹配0个字符的情况
else
return isMatch(s, p.substr(2));
}
}
};
##关于C++中空string
C++中的string和C语言的字符串有一点很像,那就是当string对象其实也是以字符’\0’结尾的,这跟C语言中一致。
这也就解释了下面这段程序不会报错的原因。
string s = ""; // s是空串
cout << (int)s[0] << endl;
//程序输出为0,也就是'\0'字符
##Solution2:动态规划
动态规划还是稍微有点难理解啊,不过至少要牢记递归的方法!
我们也可以用DP来解,定义一个二维的DP数组,其中dp[i][j]表示s[0,i)和p[0,j)是否match,然后有下面三种情况(下面部分摘自这个帖子):
- P[i][j] = P[i - 1][j - 1], if p[j - 1] != ‘*’ && (s[i - 1] == p[j - 1] || p[j - 1] == ‘.’);
- P[i][j] = P[i][j - 2], if p[j - 1] == ‘*’ and the pattern repeats for 0 times;
- P[i][j] = P[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == ‘.’), if p[j - 1] == ‘*’ and the pattern repeats for at least 1 times.
class Solution {
public:
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;
for (int i = 0; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (j > 1 && p[j - 1] == '*') {
dp[i][j] = dp[i][j - 2]
|| (i > 0 && (s[i - 1] == p[j - 2]
|| p[j - 2] == '.') && dp[i - 1][j]);
} else {
dp[i][j] = i > 0 && dp[i - 1][j - 1]
&& (s[i - 1] == p[j - 1] || p[j - 1] == '.');
}
}
}
return dp[m][n];
}
};