LeetCode-10 正则表达式匹配

这篇博客详细介绍了如何使用动态规划解决LeetCode上的10号问题——正则表达式匹配。通过定义dp数组,博主阐述了状态转移方程,并对不同情况进行讨论,包括字符匹配、'.'和'*'的处理。文章还给出了初始化dp数组的方法和遍历顺序,最后提供了问题的解决方案代码。
摘要由CSDN通过智能技术生成

LeetCode-10 正则表达式匹配

动态规划

10. 正则表达式匹配

dp数组含义 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示 s [ 0 : i − 1 ] s[0:i-1] s[0:i1] 能否被 p [ 0 : j − 1 ] p[0:j-1] p[0:j1] 成功匹配。

状态转移方程

  • 如果 s [ i − 1 ] = = p [ j − 1 ] s[i-1]==p[j-1] s[i1]==p[j1] ,那么当前字符是匹配成功了,整个子串是否匹配成功取决于之前的子串能否匹配,即 d p [ i ] [ j ] = d [ i − 1 ] [ j − 1 ] dp[i][j]=d[i-1][j-1] dp[i][j]=d[i1][j1]
  • 如果 s [ i − 1 ] ≠ p [ j − 1 ] s[i-1]\ne p[j-1] s[i1]=p[j1] ,可以按 p [ j − 1 ] p[j-1] p[j1] 是什么分三种情况:
    • 如果 p [ j − 1 ] p[j-1] p[j1].* 之外的字符,那肯定不匹配了, d p [ i ] [ j ] = f a l s e dp[i][j]=false dp[i][j]=false
    • 如果 p [ j − 1 ] = = ′ . ′ p[j-1]=='.' p[j1]==. ,由于 . 可以匹配任何字符,因此当前字符也肯定匹配成功了,还是取决于之前的子串,即 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] dp[i][j]=dp[i-1][j-1] dp[i][j]=dp[i1][j1]
    • 如果 p [ j − 1 ] = = ′ ∗ ′ p[j-1]=='*' p[j1]== ,情况比较复杂,需要再看 p [ j − 2 ] p[j-2] p[j2] s [ i − 1 ] s[i-1] s[i1] 的关系,因为 p [ j − 2 ] p[j-2] p[j2] 要与 s [ i − 1 ] s[i-1] s[i1] 匹配上, p [ j − 1 ] p[j-1] p[j1] 的这个 * 才有用
      • 而所谓 ”匹配上“,可能有两种情况,一个是字符相同,即 p [ j − 2 ] = s [ i − 1 ] p[j-2]=s[i-1] p[j2]=s[i1];另一个是 p [ j − 2 ] p[j-2] p[j2]. ,匹配任意字符。可以再按照 p [ j − 1 ] p[j-1] p[j1] 这个 * s [ i − 1 ] s[i-1] s[i1] 这个字符出现几次来分,零次、一次或两次及以上:
        • p [ j − 1 ] p[j-1] p[j1] 匹配零个 s s s 中字符,相当于删掉 * 自己及其之前的一个字符,看能不能匹配成功,比如 ### 和 ###a* ,这时 d p [ i ] [ j ] = d p [ i ] [ j − 2 ] dp[i][j]=dp[i][j-2] dp[i][j]=dp[i][j2]
        • p [ j − 1 ] p[j-1] p[j1] 匹配一个 s s s 中字符,相当于把 * 自己删掉,看能不能匹配成功,比如 ### 和 ###*,这时 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 2 ] dp[i][j]=dp[i-1][j-2] dp[i][j]=dp[i1][j2]
        • p [ j − 1 ] p[j-1] p[j1] 匹配多个 s s s 中字符,这时 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j] dp[i][j]=dp[i1][j]
        • 注意,以上三种情况只要满足一种即可,是 的关系。
      • 如果未能匹配上,即 $p[j-2]\ne s[i-1] $ 且 p [ j − 2 ] ≠ ′ . ′ p[j-2]\ne '.' p[j2]=. ,这时 p [ j − 1 ] p[j-1] p[j1] 的这个 * 可以把没能匹配上的 p [ j − 2 ] p[j-2] p[j2] 删掉,因此就取决于再之前的子串是否匹配: d p [ i ] [ j ] = d p [ i ] [ j − 2 ] dp[i][j]=dp[i][j-2] dp[i][j]=dp[i][j2]

初始化

首先 d p [ 0 ] [ 0 ] dp[0][0] dp[0][0] s s s p p p 均为空时, 认为是可以匹配的,之后的 d p [ 0 ] [ j ] dp[0][j] dp[0][j] 要先看 p [ j − 1 ] p[j-1] p[j1] 是否为 * ,若为 * ,则 d p [ 0 ] [ j ] = d p [ 0 ] [ j − 2 ] dp[0][j]=dp[0][j-2] dp[0][j]=dp[0][j2]

其他位置均初始化为 f a l s e false false

遍历顺序

从前到后即可

class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size(), n = p.size();
        vector<vector<bool>> dp(m+1, vector<bool> (n+1, false));
        dp[0][0] = true;
        for (int j=1; j<n+1; ++j) {
            if (p[j-1] == '*') dp[0][j] = dp[0][j-2];
        }
        for (int i=1; i<m+1; ++i) {
            for (int j=1; j<n+1; ++j) {
                if (s[i-1] == p[j-1] || p[j-1] == '.') dp[i][j] = dp[i-1][j-1];
                else if (p[j-1] == '*') {
                    if (s[i-1] == p[j-2] || p[j-2] == '.') {
                        dp[i][j] = dp[i][j-2] || dp[i-1][j-2] || dp[i-1][j];
                    }
                    else {
                        dp[i][j] = dp[i][j-2];
                    }
                }
            }
        }
        return dp[m][n];
    }
};

Ref:

https://leetcode.cn/problems/regular-expression-matching/solution/shou-hui-tu-jie-wo-tai-nan-liao-by-hyj8/

https://leetcode.cn/problems/regular-expression-matching/solution/dong-tai-gui-hua-zen-yao-cong-0kai-shi-si-kao-da-b/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值