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
思路
想来想去没有什么思路,试了几次按照当前位的不同分类处理,都是wrong answer。然后就想去看看正则表达式,然后怎么的就看到了NFA和DFA,然后又看到的编译原理。。。深深的给跪了,木有学过编译原理。然后我还真的就去看NFA和DFA了,找来找去在博客园这里上找到了一篇由正则表达式生成NFA的,这里有个NFA和DFA的介绍以及转化的例子,实在受不了了,没有继续找着看。想来,这么一道面试题,应该也不至于这样吧。又Google找到了这个居然用动态规划,好吧。就这样吧,不过我觉得其实懂一点正则表达式的规则或者匹配规则会更容易知道怎么去设计算法。比如为什么按照*(p+1)是不是'*'来分类。之前有一个判断是不是回文的用动态规划来判断,这次也是。看来字符串匹配之类的动态规划貌似挺管用。代码基本与那位的一样,好吧。注明了,应该不算抄袭。看那篇博客的一个评论说,这个是top-down的递归,无法发挥动态规划的优势。确实是这样的,不过bottom-up的估计得对p进行拆分,尤其在‘*’附近,s也得拆,不好办。
class Solution {
public:
bool isMatch(const char *s, const char *p) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(*p == '\0') return *s == '\0';
if(*(p+1)=='*')
{
while(*s == *p || (*s != '\0' && *p == '.'))
{
if(isMatch(s,p+2))
return true;
s++;
}
return isMatch(s,p+2);
}
else
{
if(*s == *p || (*s != '\0' && *p == '.'))
return isMatch(s+1,p+1);
else
return false;
}
}
};