10_Regular_Expression_Matching 正则表达式匹配

题目描述

给你一个字符串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 
#include 
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 正则表达式匹配)