力扣10.正则表达式匹配(动态规划)

动态规划(Dynamic Programming)思想

把「原问题」分解为若干个重叠的子问题」,每个子问题的求解过程都构成一个 「阶段」。在完成一个阶段的计算之后,动态规划方法才会执行下一个阶段的计算。
在求解子问题的过程中,按照「自顶向下的记忆化搜索方法」或者「自底向上的递推方法」求解出「子问题的解」,把结果存储在表格中,当需要再次求解此子问题时,直接从表格中查询该子问题的解,从而避免了大量的重复计算。
在分解之后得到的子问题往往是相互联系的,不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)

解题步骤:
1、定义一个状态,这是一个最优解的结构特征
2、进行状态递推,得到递推公式
3、进行初始化
4、返回结果

力扣10.正则表达式匹配

在这里插入图片描述 '*'可以复制0、1或多个前一个元素

完成匹配需要s的前i个元素和p的前j个元素完全匹配,如果第i个元素与第j个元素相等,那么比较前i-1个字符与j-1个字符是否相等,相等则完成匹配
那么问题转化为比较前i-1和前j-1个元素。如果第i-1个元素与第j-1个元素相等,那么比较前i-2个字符与j-2个字符是否相等
…直到最后只用比较一个元素

把这样一个大问题逐步拆成多个小问题,再把小问题的解逐一合并变成大问题的解,就是动态规划。此时需要一个记忆化容器去存储做过的事情,避免重复计算。

声明一个二维数组f[ ][ ]
①当p [ j ] !=‘✳’ 的时候
这时候s和p匹配就需要s的前i-1个元素与p的前j-1个元素相等,或者p[ j ]=‘.’
②当p[ j ]='✳’的时候
(1)当‘✳’表明匹配0个字符的时候,j和j-1消失,则i匹配j-2…
(2)当‘✳’表明取1个字符的时候,则i匹配j-1,i-1匹配j-2…
(3)当‘✳’表明取2个字符的时候,则i匹配j-1,i-1匹配j-1,i-2匹配j-2…
即f(i,j)=f(i,j-2) || f(i-1,j-2) &&f(i,j-1) || f(i-2,j-2) && f(i-1,j-1) &&f(i,j-1) -------------- ①
则f(i-1,j)=f(i-1,j-2) || f(i-2,j-2) &&f(i-1,j-1) || f(i-3,j-2) && f(i-2,j-1) &&f(i-1,j-1)--------------②

根据①②式可得递推式f(i,j)=f(i,j-2) || f(i-1,j) && f(i,j-1)
故整理可得:

class Solution {
public:
    bool isMatch(string s, string p) {
        int n = s.length();
        int m = p.length();

        vector<vector<bool>> f(n + 1, vector<bool>(m + 1));
        f[0][0] = true;

        for (int i = 0; i <= n; i++) { // s可能为空
            for (int j = 1; j <= m; j++) {
                if (p[j - 1] != '*') {
                    f[i][j] = i && j && f[i - 1][j - 1] &&
                              (s[i - 1] == p[j - 1] || p[j - 1] == '.');
                } else {
                    f[i][j] = (j >= 2 && f[i][j - 2]) ||
                              (i && j && f[i - 1][j] &&
                               (s[i - 1] == p[j - 2] || p[j - 2] == '.'));
                }
            }
        }
        return f[n][m];
    }
};
  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值