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)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
分析:
(1)注意左边是常规字符串,只有右边是正则。开始我认为左边也可能是正则,形如“a*ab” “b*c”,那就太复杂了。还好此题只有右边是正则。
(2)正则表达式默认合法,即不会出现 **ab.***这种歧义的非法正则
(3)左边以一个字母为单位,右边则有可能是2个字母或者一个字母为单位,这样用递归可以解决,思路上也算比较清晰
(4)如果用C++写,那么string可能存在字串拷贝的情况,所以复杂度上略有冗余。可以用const string&防止拷贝的发生
(5)整体思路:从左边取出最前字符,再从右边取出第一个字符比较,右边的字符可能有以下几种:a . a* .* 。因此只需要对这几种情况进行讨论然后递归即可(复杂度当然较高,不过先解决问题再说)
class Solution {
public:
bool isMatch(string s1, string s2) {
return isMatch2(s1,s2,0,0);
}
bool isMatch2(const string& s1, const string& s2, int idx1,int idx2 ) {
//if to the end of s1
if(s1[idx1] == '\0'){
if(s2[idx2] == '\0')
return true;
else if(s2[idx2 + 1] == '\0')
return false;
else{
if(s2[idx2 + 1] == '*')
return isMatch2(s1,s2,idx1,idx2 + 2);
else
return false;
}
}
//if to the end of s2
if(s2[idx2] == '\0')
return false;
else if(s2[idx2 + 1] == '\0'){
if(s2[idx2] == s1[idx1] || s2[idx2] == '.')
return isMatch2(s1,s2,idx1 + 1,idx2 + 1);
else
return false;
}
//normal scenrio
char c1 = s1[idx1];
char c2 = s2[idx2];
char c2_next = s2[idx2 + 1];
if(c2 != '.'){
if(c2_next != '*'){
if(c1 == c2){//eg:a ab
return isMatch2(s1,s2,idx1 + 1,idx2 + 1);
}
else{//eg:a cb
return false;
}
}
else{
if(c1 == c2){//eg:a a*
return isMatch2(s1, s2, idx1 + 1, idx2) || isMatch2(s1, s2, idx1, idx2 + 2);
}
else{//eg:a b*
return isMatch2(s1, s2, idx1, idx2 + 2);
}
}
}
else{
if(c2_next != '*'){
return isMatch2(s1, s2, idx1 + 1, idx2 + 1);
}
else{
return isMatch2(s1, s2, idx1 + 1, idx2) || isMatch2(s1, s2, idx1, idx2 + 2);
}
}
return false;
}
};