剑指offer之正则表达式匹配

1.题目描述

请实现一个函数用来匹配包含’.’和’‘的正则表达式。模式中的字符’.’表示任意一个字符,而’‘表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串”aaa”与模式”a.a”和”ab*ac*a”匹配,但与”aa.a”及”ab*a”均不匹配。

2.分析

  • 这个正则表达式函数只涉及到’.’和’*’两个字符的匹配匹配
  • 对于’.’匹配,只要把’.’字符特殊处理,’.’可以和任何字符匹配
  • 对于’*’匹配,这就比较麻烦,要考虑全所有情况。

这里对于’*’做详细分析:

  • 对于’*’匹配,如a* ,a的个数范围是[0,+)
  • 如果匹配0个字符,那么模式向后移动2个字符
  • 如果匹配n(n>=1)个字符,那么字符串向后移动一个字符,模式不变

3.源代码


bool myMatch(const char* str,const char* pattern)
{
    //字符串为空指针,则匹配失败
    if(str==nullptr||pattern==nullptr)
        return false;

    return myMatchCore(str,pattern);
}
bool myMatchCore(const char* str, const char* pattern)
{
    //递归匹配找到终止条件
    if(*str == '\0' &&*pattern == '\0')
        return true;
    //下一个字符是否是'*'
    if(*(pattern+1) == '*')
    {
        if(*str == *pattern ||(*pattern =='.' && *str != '\0'))
        {
            // 继续留在有限状态机的当前状态,.*匹配[0,+)个字符,匹配下一个字符
            return  myMatchCore(str+1,pattern)||
                    // 略过一个'*',匹配0给字符
                    myMatchCore(str,pattern+2);
        }
        else
            return myMatchCore(str,pattern+2);
    }

    //匹配下一个字符
    if(*str == *pattern ||(*pattern =='.' && *str != '\0'))
        return myMatchCore(str+1,pattern+1);

    return false;
}

完整代码

#include <iostream>
using std::cout;
using std::endl;
bool myMatchCore(const char* str, const char* pattern);

bool myMatch(const char* str,const char* pattern)
{
    if(str==nullptr||pattern==nullptr)
        return false;

    return myMatchCore(str,pattern);
}
bool myMatchCore(const char* str, const char* pattern)
{
    if(*str == '\0' &&*pattern == '\0')
        return true;

    if(*(pattern+1) == '*')
    {
        if(*str == *pattern ||(*pattern =='.' && *str != '\0'))
        {
            // 继续留在有限状态机的当前状态,.*匹配[0,+)个字符,匹配下一个字符
            return  myMatchCore(str+1,pattern)||
                    // 略过一个'*',匹配0给字符
                    myMatchCore(str,pattern+2);
        }
        else
            return myMatchCore(str,pattern+2);
    }

    if(*str == *pattern ||(*pattern =='.' && *str != '\0'))
        return myMatchCore(str+1,pattern+1);

    return false;
}
void test(const char* string,const char* pattern)
{
    cout <<"str:"<<string<<" pattern:"<<pattern;
    if(myMatch(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.结论

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

猜你喜欢

转载自blog.csdn.net/zqw_yaomin/article/details/81604050