【发布时间】:2012-09-18 02:03:20
【问题描述】:
Implement regular expression matching with support for ‘.’ and ‘*’.
‘.’ 匹配任何单个字符。 ‘*’ 匹配零个或多个前面的元素。匹配应该覆盖整个输入字符串(不是部分)。
一些例子:
isMatch(“aa”,”a”) → 假
isMatch(“aa”,”aa”) → 真
isMatch(“aaa”,”aa”) → 假
isMatch(“aa”, “a*”) → 真
isMatch(“aa”, “.*”) → 真
isMatch(“ab”, “.*”) → 真
isMatch(“aab”, “c*a*b”) → 真
作者给出如下解决方案,真的很漂亮。
bool isMatch(const char *s, const char *p) {
assert(s && p);
if (*p == '\0') return *s == '\0';
// next char is not '*': must match current character
if (*(p+1) != '*') {
assert(*p != '*');
return ((*p == *s) || (*p == '.' && *s != '\0')) && isMatch(s+1, p+1);
}
// next char is '*'
while ((*p == *s) || (*p == '.' && *s != '\0')) {
if (isMatch(s, p+2)) return true;
s++;
}
return isMatch(s, p+2);
}
作者还给出了一些进一步的想法:
如果您仔细考虑,您可以利用上述代码以指数复杂度运行的某些情况。
你能想出一些例子吗?你将如何制作上面的代码 效率更高?
我想出了一个需要很长时间才能得到结果的案例,而 字符串 s 和 p 的长度并不大。
s[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" p[] ="a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a *a*a*b"
谁能帮我验证这个答案? 如何看待这种寻找极端的测试题?
【问题讨论】:
-
提示:在
isMatch函数中添加一些“日志记录”以宣布其进度。从那里你应该能够设计一个通用公式,告诉你你的例子需要多少“步骤”。最终,这是一个数学(计数)问题。 :) -
@RayToal,是的,我已经做过类似的实验。我定义了一个名为
count的全局参数。然后在isMatch函数中加一。你的意思是这样的吗? -
是的,但您可能还想看看自己走了多远,而不仅仅是数数。将诸如当前索引之类的内容记录到字符串中以及递归的深度将使您对算法的工作原理产生有趣的了解。
-
@RayToal,非常感谢您的帮助。我仍然无法弄清楚如何使用“记录”技能,同时我真的很想掌握它,以便我将来可以处理所有这些情况。你能给我更多的提示吗?我不是要你帮我写代码。或者有没有关于“记录”技能的例子?非常感谢您的帮助
-
哦,我所说的记录只是指普通的旧
printf。我会提交一个答案。
标签: algorithm recursion string-matching