10. Regular Expression Matching
Given an input string (
s
) and a pattern (p
), 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 entireinput string (not partial).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like.
or*
.Example 1:
Input: s = "aa" p = "a" Output: false Explanation: "a" does not match the entire string "aa".Example 2:
Input: s = "aa" p = "a*" Output: true Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".Example 3:
Input: s = "ab" p = ".*" Output: true Explanation: ".*" means "zero or more (*) of any character (.)".Example 4:
Input: s = "aab" p = "c*a*b" Output: true Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".Example 5:
Input: s = "mississippi" p = "mis*is*p*." Output: false
Given an input string (
s
) and a pattern (p
), implement wildcard pattern matching with support for'?'
and'*'
.'?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence).
The matching should cover the entireinput string (not partial).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like?
or*
.Example 1:
Input: s = "aa" p = "a" Output: false Explanation: "a" does not match the entire string "aa".
Example 2:
Input: s = "aa" p = "*" Output: true Explanation: '*' matches any sequence.
Example 3:
Input: s = "cb" p = "?a" Output: false Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
Example 4:
Input: s = "adceb" p = "*a*b" Output: true Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
Example 5:
Input: s = "acdcb" p = "a*c?b" Output: false
class Solution {
public:
bool isMatch(string s, string p) {
vector<vector<bool>> dp(p.size()+1, vector<bool>(s.size()+1, false));
dp[0][0] = true;
for(int i = 0; i < p.size(); ++i){
if(p[i] == '*' && dp[i-1][0]) dp[i+1][0] = true;
}
for(int i = 0; i < p.size(); ++i){
for(int j = 0; j < s.size(); ++j){
// cout << i << ' ' << j << endl;
if(p[i] == '*'){
dp[i+1][j+1] = dp[i-1][j+1] || ((p[i-1] == '.' || p[i-1] == s[j]) && dp[i+1][j]);
}else{
dp[i+1][j+1] = ((p[i] == '.' || p[i] == s[j]) && dp[i][j]);
}
}
}
return dp.back().back();
}
};
class Solution {
public:
bool isMatch(string s, string p) {
int idx_s = 0, idx_p = 0;
int pre_s = -1, pre_p = -1;
while(idx_s < s.size()){
if(idx_p < p.size() && (s[idx_s] == p[idx_p] || p[idx_p] == '?')){
++idx_s;
++idx_p;
}else if(idx_p < p.size() && p[idx_p] == '*'){
pre_s = idx_s;
pre_p = idx_p;
++idx_p;
}else if(pre_p != -1){
idx_p = pre_p;
idx_s = pre_s+1;
}else{
return false;
}
}
while(idx_p < p.size() && p[idx_p] == '*') ++idx_p;
return idx_p == p.size();
}
};
後者之所以能用更快速的方法完成在於不同位置出現的星號的功能相同,因此後出現的星號對先出現的星號具有覆蓋作用,例如:
s:[頭]+[xx]+[匹配段1]+[xx]+[匹配段1]+[xx]+[匹配段2]+[尾]
p:[頭]+[*]+[匹配段1]+[*]+[匹配段2]
p中匹配段1匹配到s中的哪個匹配段並不重要,所以在第二個星號被讀到之後,第一個星號的信息就可以拋棄了,自然也不需要回溯(相當於s中真正被p中匹配段1匹配的段可以在一堆任意字符中左右滑動)
而前者沒有這個性質