剑指offer之正则表达式匹配

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.结论

第一,对于字符串编程的能力要好;
第二,要对正则表达式的理解;
第三,要思考全面,对于’.‘匹配很好解决,但是’*'就比较麻烦,要考虑完整;
第四,这道题使用了递归,要找好递归终止的边界

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值