正则表达式

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

解法一:
这里主要说一下自己的想法吧。
统一假设 * 前面的字符为 pre。
主要分为两种情况,一种 str 为空,一种不为空

  • 一. 当 str 为空,只能匹配以下情况,“”、“a*”、“a*b*…”等,所以我认为 pattern 应该为偶数,且每一个字符后面都应该后跟一个 ‘*’, 否则便是错误。(考虑过连续多个 ‘*’ 的出现,即错误判断,但是发现我解决不了)
  • 二. 当 str 不为空,由于 ‘*’ 前面的字符可以出现任意次。又可以分两种情况,一种能匹配,一种不能匹配。
    1. 如果不能匹配,100%跳过,出现0次
    1. 如果能匹配,又是两种情况,pre出现0次与多次,例如"a"和"a*", "“和"a*”。我们统一首先假设pre一次不出现(虽然能匹配上),然后递归执行 match() 函数,返回真,则最终返回真;返回假,pre出现次数+1,重复上述过程。直到 str 或者 pattern其中一个遍历完。
  • 遍历完还没完事那,还有两种情况。(1)str 遍历完, pattern没遍历完。这时,str 剩余字符为‘\0’,pattern则还有其他剩余字符。执行一次pattern剩余字符的判断,是否符合第一种情况,即第一条。看两个个例子吧:“aaa” 和 “aaa*”, “aaa” 和 “aa*b”。(2)pattern 遍历完,但是 str 没有遍历完,这是肯定错误的。代码超时,自己测了一些感觉没问题。
class Solution {
    public:
    bool match(char* str, char* pattern)
    {
        if (*str == '\0')
        {
            if (*pattern == '\0')
                return true;
            else
                return judge(pattern);
        }

        int slen = 0, plen = 0;
        slen = size(str);
        plen = size(pattern);
        int sIndex = 0, pIndex = 0;

        while (sIndex < slen && pIndex < plen)
        {
            //遇到*,直接跳过
            if (pattern[pIndex + 1] == '*')//'\0'-stop
            {
                if (pattern[pIndex] != str[sIndex] && pattern[pIndex] != '.')
                {
                    pIndex += 2;
                    continue;
                }
                //跳过之后可以匹配
                if (pattern[pIndex + 2] == str[sIndex] || pattern[pIndex + 2] == '.')
                {
                    if (match(str + sIndex, pattern + pIndex + 2))//跳过之后完全匹配
                        return true;
                }
                else//跳过之后不匹配,那就只能当前匹配
                {
                    //匹配成功
                    if (pattern[pIndex] == str[sIndex] || pattern[pIndex] == '.')
                        sIndex++;
                    else
                        return false;
                }
            }
            else
            {
                if (pattern[pIndex] == str[sIndex] || pattern[pIndex] == '.')
                {
                    sIndex++;
                    pIndex++;
                }
                else
                    return false;
            }
        }
        if (sIndex >= slen && pIndex < plen)
            return judge(pattern + pIndex);
        if (pIndex >= plen && sIndex < slen)
            return false;
        return true;
    }
    private:
    bool judge(char *pattern)
    {
        int index = 0;
        int plen = 0;

        plen = size(pattern);
        if (plen % 2 != 0)
            return false;
        for (index; index < plen; index += 2)
            if (pattern[index + 1] != '*')
                return false;

        return true;
    }

    int size(char *ch)
    {
        int length = 0;
        for (; *ch != '\0'; ch++) length++;
        return length;
    }
};

思路比较乱,欢迎指正。

解法二:
这里借用牛客大佬的东西,如果涉及侵权,直接删掉。
哎,情况都考虑到了,就是思路比较复杂,语言表达能力也不行,努力吧。。。
以下来源牛客帖子,链接如下
链接:https://www.nowcoder.com/questionTerminal/45327ae22b7b413ea21df13ee7d6429c
来源:牛客网

/*
    解这题需要把题意仔细研究清楚,反正我试了好多次才明白的。
    首先,考虑特殊情况:
         1>两个字符串都为空,返回true
         2>当第一个字符串不空,而第二个字符串空了,返回false(因为这样,就无法
            匹配成功了,而如果第一个字符串空了,第二个字符串非空,还是可能匹配成
            功的,比如第二个字符串是“a*a*a*a*”,由于‘*’之前的元素可以出现0次,
            所以有可能匹配成功)
    之后就开始匹配第一个字符,这里有两种可能:匹配成功或匹配失败。但考虑到pattern
    下一个字符可能是‘*’, 这里我们分两种情况讨论:pattern下一个字符为‘*’或
    不为‘*’:
          1>pattern下一个字符不为‘*’:这种情况比较简单,直接匹配当前字符。如果
            匹配成功,继续匹配下一个;如果匹配失败,直接返回false。注意这里的
            “匹配成功”,除了两个字符相同的情况外,还有一种情况,就是pattern的
            当前字符为‘.’,同时str的当前字符不为‘\0’。
          2>pattern下一个字符为‘*’时,稍微复杂一些,因为‘*’可以代表0个或多个。
            这里把这些情况都考虑到:
               a>当‘*’匹配0个字符时,str当前字符不变,pattern当前字符后移两位,
                跳过这个‘*’符号;
               b>当‘*’匹配1个或多个时,str当前字符移向下一个,pattern当前字符
                不变。(这里匹配1个或多个可以看成一种情况,因为:当匹配一个时,
                由于str移到了下一个字符,而pattern字符不变,就回到了上边的情况a;
                当匹配多于一个字符时,相当于从str的下一个字符继续开始匹配)
    之后再写代码就很简单了。
*/
class Solution {
    public:
    bool match(char* str, char* pattern)
    {
        if (*str == '\0' && *pattern == '\0')
            return true;
        if (*str != '\0' && *pattern == '\0')
            return false;
        
        if (*(pattern + 1) != '*')
        {
            if (*pattern == *str || (*str != '\0' && *pattern == '.'))
                return match(str+1, pattern + 1);
            else
                return false;
        }
        else
        {
            if (*pattern == *str || (*str != '\0' && *pattern == '.'))
                return match(str + 1, pattern) || match(str, pattern + 2);
            else
                return match(str, pattern + 2);
        }
    }
};
总结(自己看):看完思路之后,自己写了下代码,漏了判断 *str != '\0' 的判断,倒数第6行的 || 也写成了 &&。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值