10. Regular Expression Matching
10. Regular Expression Matching
题解:
方法一:动态规划
dp[i][j]表示 s 的前 i 个元素和 p 的前 j 个元素可以匹配,则状态转移方程为:
if ( s[i] == p[j] ) dp[i][j] = dp[i-1][j-1]
if( p[j] == '.' ) dp[i][j] = dp[i-1][j-1]
if( p[j] == '*' )
if( p[j-1] != s[i] ) dp[i][j] = dp[i][j-2] // 令 * 表示empty
if( p[j-1] == s[i] || p[j-1] == '.' ) dp[i][j] = dp[i-1][j] || dp[i][j-1] || dp[i][j-2] // 即 *代表多字符 | *代表单字符 | *代表无字符,##aaa 与 ##a* 匹配情况,* 号代表多个字符 || ##a 与 ##a* 匹配的情况,* 等于不存在 || ### 与 ###a*匹配,* 吃掉前面的 a ,代表 empty。
细节请参考源码,注意dp下标和s, p下标的区别,前者范围是0 ~ len+1, 后者是0 ~ len
class Solution {
public:
bool isMatch(string s, string p) {
int slen = s.size(), plen = p.size();
vector< vector<bool> > dp(slen+1, vector<bool>(plen+1));
dp[0][0] = true;
for(int j = 0; j < plen; j++){ // 初始化 p 匹配 空串s
if(p[j] == '*' && j >= 1 && dp[0][j-1]) dp[0][j+1] = true;
}
for(int i = 1; i <= slen; i++){ // 初始化 空串p 匹配 s
dp[i][0] = false;
}
for(int i = 0; i < slen; i++){
for(int j = 0; j < plen; j++){
if(s[i] == p[j] || p[j] == '.'){
dp[i+1][j+1] = dp[i][j];
}
else if(p[j] == '*'){
if(s[i] == p[j-1] || p[j-1] == '.'){
if(j-1 >= 0){
dp[i+1][j+1] = dp[i][j+1] || dp[i+1][j] || dp[i+1][j-1];
}
else{
dp[i+1][j+1] = false;
}
}
else{
if(j-1 >= 0){
dp[i+1][j+1] = dp[i+1][j-1];
}
else{
dp[i+1][j+1] = false;
}
}
}
else{
dp[i+1][j+1] = false;
}
}
}
return dp[slen][plen];
}
};
方法二:递归比较
首先在递归之前明确一点,假如有 * 出现,则必定从 p 的第 2 个开始,算法比较简单,直接看代码。
class Solution {
public:
bool isMatch(string s, string p) {
if(p.size() == 0){
return (s.size() == p.size());
}
bool first_match = s.size() > 0 && (p[0] == '.' || s[0] == p[0]);
if(p.size() >= 2 && p[1] == '*'){
return isMatch(s, p.substr(2)) || (first_match && isMatch(s.substr(1), p));
}
else{
return first_match && isMatch(s.substr(1), p.substr(1));
}
}
};
方法三:
前方高能预警!!
class Solution {
public:
bool isMatch(string s, string p) {
return regex_match(s, regex(p));
}
};