题目描述
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配。
思路1:递归,参考剑指offer书上解法。
class Solution {
public:
bool match(char* str, char* pattern)
{
if (str == nullptr || pattern == nullptr) return false;
return matchSub(str, pattern);
}
bool matchSub(char* str, char* pattern) {
if (*str == '\0'&&*pattern == '\0') return true;
if (*str != '\0'&&*pattern == '\0') return false; // *str == '\0'&&*pattern != '\0' 用例:"",".*" 为true
if (*(pattern + 1) == '*') {
if (*pattern == *str || (*pattern == '.'&& *str != '\0'))
return matchSub(str + 1, pattern + 2)
|| matchSub(str + 1, pattern)
|| matchSub(str, pattern + 2);
else
return matchSub(str, pattern + 2);
}
if (*pattern == *str || (*pattern == '.'&& *str!='\0'))
return matchSub(str + 1, pattern + 1);
return false;
}
};
思路2:含有重叠子问题,考虑动态规划
class Solution {
public:
bool match(string str, string pattern)
{
if (pattern.empty()) return str.empty();
str = " " + str; //前面加某一相同字符,防止aa a* 或者ab c*ab这样的匹配,避免复杂的初始化操作
pattern = " " + pattern;
vector<vector<bool>> dp(str.size() + 1, vector<bool>(pattern.size() + 1, false));
dp[0][0] = true;
for (int i = 1; i < str.size()+1; i++) {
for (int j = 1; j < pattern.size()+1; j++) {
if (pattern[j - 1] == '.' || pattern[j - 1] == str[i - 1])
dp[i][j] = dp[i - 1][j - 1];
else if (pattern[j - 1] == '*') {
if (pattern[j - 2] != str[i - 1] && pattern[j - 2] != '.')
dp[i][j] = dp[i][j - 2]; //匹配0次 aaa ab*aa
else
dp[i][j] = dp[i - 1][j] //匹配多次 aaaa aa*a -> 转换为匹配0次
|| dp[i][j - 2]; //匹配0次 aaa aa*a
}
}
}
return dp[str.size()][pattern.size()]; //返回最后字符的匹配状态
}
};
总结:
- 如果 p[j] == s[i] : dp[i][j] = dp[i-1][j-1]
- 如果 p[j] == ‘.’ : dp[i][j] = dp[i-1][j-1]
- 如果 p[j] == ‘*’ :
1> 如果 p[j-1] != s[i] : dp[i][j] = dp[i][j-2]
2> 如果 p[j-1] == s[i] || p[j-1] == ‘.’:- dp[i][j] = dp[i-1][j] 匹配多次
- dp[i][j] = dp[i][j-2] 匹配0次