• 【LeetCode-递归】正则表达式匹配


    题目描述

    给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

    '.' 匹配任意单个字符
    '*' 匹配零个或多个前面的那一个元素
    

    所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
    说明:

    • s 可能为空,且只包含从 a-z 的小写字母。
    • p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

    题目链接: https://leetcode-cn.com/problems/regular-expression-matching/

    思路

    使用递归来做。使用两个指针 sPos 和 pPos 分别表示 s 和 p 的当前进行匹配位置,sPos 和 pPos 均初始化为 0。

    如果 p[pPos] == '.',因为 '.' 能匹配任意单个字符,所以将 sPos+1、pPos+1 匹配下一个字符即可。

    如果模式串 p 当前字符的下一个字符也就是 p[pPos+1]=='*',那么:

    • 如果 s[sPos] 和 p[pPos] 可以匹配:
      • 可以将 sPos 保持不动,将 pPos 后移两个位置,例如 s="aa", p="a*aa";
      • 也可以将 sPos 后移一个位置,而 pPos 保持不动,例如 s="aaaaa", p="a*";
    • 否则:
      • 将 sPos 保持不动,将 pPos 后移两个位置,例如 s="aab", p="b*aab";

    在写代码的时候,要根据模式串 p 当前字符的下一个字符也就是 p[pPos+1] 是否为 '*' 分两种情况讨论,具体如下:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            int sPos = 0, pPos = 0;
            return match(s, p, sPos, pPos);
        }
    
        bool match(string& s, string& p, int sPos, int pPos){
            int lens = s.length(), lenp = p.length();
            if(sPos>=lens && pPos>=lenp) return true;
            if(sPos>lens || pPos>=lenp) return false; // 注意这个条件
    
            if(pPos+1<lenp && p[pPos+1]=='*'){
                if(sPos==lens || s[sPos]==p[pPos] || p[pPos]=='.'){
                    return match(s, p, sPos, pPos+2) || // 不匹配直接跳过
                           match(s, p, sPos+1, pPos);  // 匹配一个或多个字符
                }else return match(s, p, sPos, pPos+2);
            } else {
                if(sPos==lens) return false;
                if(s[sPos]==p[pPos] || p[pPos]=='.') return match(s, p, sPos+1, pPos+1);
                else return false;
            }
        }
    };
    

    需要注意的是返回的条件是 sPos>lens || pPos>=lenp,而不是 sPos>=lens || pPos>=lenp,因为可能会出现 s="a",p="ab*" 的情况。还有一点要注意的是 match 函数的前两个字符串参数要使用引用,不然会超时。

    用指针写代码会更简洁:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            int sPos = 0, pPos = 0;
            return match(s.data(), p.data());
        }
    
        bool match(char* s, char* p){
            if(!*s && !*p) return true;
            if(*s && !*p) return false;
    
            if(*(p+1)=='*'){
                if(*s == *p || (*p == '.' && *s != '')) return match(s, p + 2) || match(s + 1, p);
                else return match(s, p + 2);
            }else{
                if(*s==*p || (*p=='.' && *s!='')) return match(s+1, p+1);
                else return false;
            }
        }
    };
    

    参考

    1、https://leetcode-cn.com/problems/regular-expression-matching/solution/zheng-ze-biao-da-shi-pi-pei-by-whyatlc-2/
    2、https://leetcode-cn.com/problems/regular-expression-matching/solution/cjian-ji-dai-ma-ti-jie-ming-tian-xie-by-orangeman/

  • 相关阅读:
    HTML目录
    Java目录
    高级Swing——列表
    Java Web目录
    mongodb目录
    MySQL目录
    基于C++11的线程池
    数据库架构的演变
    cocos2dx-3.0(14)------SpriteBatchNode与SpriteFrameCache加快渲染
    cocos2d-x 托付模式的巧妙运用——附源代码(一)
  • 原文地址:https://www.cnblogs.com/flix/p/13171678.html
Copyright © 2020-2023  润新知