1.题目描述
请实现一个函数用来匹配包含’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"及"ab*a"均不匹配。
2.分析
- 这个正则表达式函数只涉及到’.‘和’*'两个字符的匹配匹配
- 对于’.‘匹配,只要把’.‘字符特殊处理,’.'可以和任何字符匹配
- 对于’*'匹配,这就比较麻烦,要考虑全所有情况。
这里对于’*'做详细分析:
- 对于’*'匹配,如
a*
,a的个数范围是[0,+) - 如果匹配0个字符,那么模式向后移动2个字符
- 如果匹配n(n>=1)个字符,那么字符串向后移动一个字符,模式不变
3.源代码
bool match(const char* str, const char* pattern)
{
if(str == NULL || pattern == NULL)
return false;
//字符串匹配到尾部,都满足要求,则返回true
if(*str == '\0' && *pattern == '\0')
return true;
//pattern已经到最后,但是str还没有匹配结束,则匹配失败
if(*str != '\0' && *pattern == '\0')
return false;
//如果pattern下一个字符为'*',则分成两个情况:
if(*(pattern + 1) == '*')
{
//情况一:当前字符相等,则str向后移动一位或者pattern移动2位
if(*str == *pattern || (*str != '\0' && *pattern == '.'))
return match(str + 1, pattern) || match(str, pattern + 2);
//情况二:反之,当前字符不相等,则attern向后移动2位
else
return match(str, pattern + 2);
}
//如果pattern下一个字符不是'*',那么情况就一种
else
{
//如果当前字符相等,则str和pattern都向后移动一位,继续比较;反之,返回false
if(*str == *pattern || (*str != '\0' && *pattern == '.'))
return match(str + 1, pattern + 1);
else
return false;
}
}
完整代码
#include <iostream>
using std::cout;
using std::endl;
bool match(const char* str, const char* pattern)
{
if(str == NULL || pattern == NULL)
return false;
//字符串匹配到尾部,都满足要求,则返回true
if(*str == '\0' && *pattern == '\0')
return true;
//pattern已经到最后,但是str还没有匹配结束,则匹配失败
if(*str != '\0' && *pattern == '\0')
return false;
//如果pattern下一个字符为'*',则分成两个情况:
if(*(pattern + 1) == '*')
{
//情况一:当前字符相等,则str向后移动一位或者pattern移动2位
if(*str == *pattern || (*str != '\0' && *pattern == '.'))
return match(str + 1, pattern) || match(str, pattern + 2);
//情况二:反之,当前字符不相等,则attern向后移动2位
else
return match(str, pattern + 2);
}
//如果pattern下一个字符不是'*',那么情况就一种
else
{
//如果当前字符相等,则str和pattern都向后移动一位,继续比较;反之,返回false
if(*str == *pattern || (*str != '\0' && *pattern == '.'))
return match(str + 1, pattern + 1);
else
return false;
}
}
void test(const char* string,const char* pattern)
{
cout <<"str:"<<string<<" pattern:"<<pattern;
if(match(string,pattern))
cout<<" is match"<<endl;
else
cout<<" isn't match"<<endl;
}
int main()
{
test( "", "");
test( "", ".*");
test( "", ".");
test( "", "c*");
test( "a", ".*");
test("a", "a.");
test("a", "");
test("a", ".");
test("a", "ab*");
test("a", "ab*a");
test("aa", "aa");
test("aa", "a*");
test("aa", ".*");
test("aa", ".");
test( "ab", ".*");
test("ab", ".*");
test("aaa", "aa*");
test("aaa", "aa.a");
test("aaa", "a.a");
test("aaa", ".a");
test("aaa", "a*a");
test("aaa", "ab*a");
test("aaa", "ab*ac*a");
test("aaa", "ab*a*c*a");
test("aaa", ".*");
test("aab", "c*a*b");
test("aaca", "ab*a*c*a");
test("aaba", "ab*a*c*a");
test("bbbba", ".*a*a");
test("bcbbabab", ".*a*a");
test("a", ".*a*a");
test("aa", ".*a*a");
return 0;
}
4.结论
第一,对于字符串编程的能力要好;
第二,要对正则表达式的理解;
第三,要思考全面,对于’.‘匹配很好解决,但是’*'就比较麻烦,要考虑完整;
第四,这道题使用了递归,要找好递归终止的边界