Description
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)
Example
isMatch(“aa”,“a”) → false
isMatch(“aa”,“aa”) → true
isMatch(“aaa”,“aa”) → false
isMatch(“aa”, “a*”) → true
isMatch(“aa”, “.") → true
isMatch(“ab”, ".”) → true
isMatch(“aab”, “cab”) → true
Analyse
一开始以为这又是一道字符串处理题,结果越做越不对,然后再回头看看难度。。。为Hard。。然后就知道。。这道题不那么简单。。
冷静下来之后,仔细看看,这道题应该用动态规划比较好做。
类似一种匹配最长公共子串的方式,ans[i][j]为s串的前i个字符和p串的前j个字符匹配成功,则最终结果为ans[len1][len2],(len1为s串的长度,len2为p串的长度)。
转移方程为:
- ans[i][j]=ans[i][j - 2],若p[j - 1]==‘*’且重复次数为0。
- ans[i][j]=ans[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == ‘.’),若p[j - 1]==‘*’重复次数至少为1次。(星号前为.或相同字符)
- ans[i][j]=ans[i - 1][j - 1],若p[j - 1] != ‘*’ && (s[i - 1] == p[j - 1] || p[j - 1] == ‘.’)。
大体思考方向为:判断分为有星号和没有星号的情况,没有星号的情况比较好处理,当有.和两个字符相同的时候都可以认为相同。而有星号的情况需要分类讨论,星号可以当作没有,也可以当作至少一个相同的符号,然后分类讨论,相信也不是很难。
Code
class Solution {
public:
bool isMatch(string s, string p) {
int len1 = s.length(), len2 = p.length();
vector<vector<bool> > ans(len1 + 1, vector<bool> (len2 + 1, false));
ans[0][0] = true;
for (int i = 0; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (p[j - 1] == '*') { //星号的情况
ans[i][j] = ans[i][j - 2];
if (i > 0 && (s[i - 1] == p[j - 2] || p[j - 2] == '.')) {
ans[i][j] = ans[i][j - 2] || ans[i - 1][j];
}
} else { //无星号的情况
if (i > 0 && (s[i - 1] == p[j - 1] || p[j - 1] == '.')) {
ans[i][j] = ans[i - 1][j - 1];
}
}
}
}
return ans[len1][len2];
}
};