美文网首页
10_Regular_Expression_Matching 正

10_Regular_Expression_Matching 正

作者: lazy_ccccat | 来源:发表于2020-01-12 21:12 被阅读0次

    题目描述

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

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

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

    说明:

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

    示例 1:

    输入:
    s = "aa"
    p = "a"
    输出: false
    解释: "a" 无法匹配 "aa" 整个字符串。

    示例 2:

    输入:
    s = "aa"
    p = "a*"
    输出: true
    解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

    示例 3:

    输入:
    s = "ab"
    p = ".*"
    输出: true
    解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。

    示例 4:

    输入:
    s = "aab"
    p = "c*a*b"
    输出: true
    解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"

    示例 5:

    输入:
    s = "mississippi"
    p = "mis*is*p*."
    输出: false

    解法一:递归

    #include <string>
    #include <iostream>
    using namespace std;
    
    bool isMatch(string s, string p) {
        //p为空
        if (p.empty()) {
            return s.empty();
        }
        
        bool first_match = !s.empty() && (s[0] == p[0] || p[0] == '.');
        //只有p长度>=2的时候,才考虑*的存在
        if (p.size() >= 2) {
            if (p[1] == '*') {
                //两种情况, 1.pattern修改,直接跳过两个字符,表示*前面字符出现了0次
                // 2. pattern不变,表示*用前一个字符替代(代码实现上无需真的replace *, 而是p右移一位即可有该效果,你体会一下)
                return isMatch(s, p.substr(2)) || (first_match && isMatch(s.substr(1), p));
            } else {
                return first_match && isMatch(s.substr(1), p.substr(1));
            }
        } else { //p长度为1
            return (s.size() == 1) && (s == p || p == ".");
        }
    }
    
    
    int main() {
        string s = "a";
        string p = "a";
        cout << isMatch(s,p) << endl; 
    }
    

    思路

    看代码注释就很容易明白思路了,在这还是简单说一下吧。
    遇到这种问题,需要找规律的,就按长度从小到大考虑----渐进!
    你看题目给的几个case顺序都是长度从小到大的,很贴心了。
    这个题的难点就在于*的存在,它可以让前面的字符出现0次或者多次。
    注意*不能出现在第一位,因为它前面没字符,所以没意义。因此只有长度>=2时,才考虑*

    if p为空,那么s为空 true; s不空 false。
    if p长度为1 那么s长度为1 && (s==p || p == '.')才返回true; 否则返回false。
    if p长度>=2,这时需要考虑*的存在了。

    • p[1] == '*'的情况
      1. pattern直接跳过两个字符,表示*前面的字符出现0次。
        例如s="aab", p="c*a*b"的情况,需要直接跳过c*, 假装p是"a*b"然后去和s匹配。
      2. pattern不变,表示*用前一个字符替代。
        例如 s="aa", p="a*",在这里*a替代,p="aa"去和s匹配。实现上有个trick,就是不需要真的replace *,只需将p右移一位即可。
    • p[1] != '*'的情况
      那么return first_match && isMatch(s,substr(1), p.substr(1))

    理清了上述规律,下面找个case来模拟一下匹配过程。

    • s="aab", p="c*a*b"
      isMatch(s,p) = isMatch("aab", "a*b") = isMatch("aab", "aab") = true
    • s="mississippi", p="mis*is*p*"
      isMatch(s,p) = isMatch("ssissippi", "s*is*p*") = isMatch("ssissippi", "ssis*p*") = isMatch("ssippi", "s*p*") = isMatch("ssippi", "ssp*") = isMatch("ippi", "p*") = false

    Refs and TODO

    https://www.jianshu.com/p/8a8b4cba6688
    改成dp写法。

    相关文章

      网友评论

          本文标题:10_Regular_Expression_Matching 正

          本文链接:https://www.haomeiwen.com/subject/ovjtyctx.html