【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/

原文地址:https://www.cnblogs.com/flix/p/13171678.html