【极简动态规划 正则表达式匹配】

1,150 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

那就干吧! 这个专栏都是刷的题目都是关于动态规划的,我会由浅入深、循序渐进,刷题就是这样需要连续不断的记忆--艾宾浩斯记忆法2121112。动态规划的内容不多,但是都是每个程序员必备的

这道题很经典啦😄😄😄 \color{green}{这道题很经典啦😄 😄 😄 ~}

刷题之路-任重而道远啊

什么题可以选择动态规划来做?

1.计数

  • 有多少种方式走到右下角
  • 有多少种方法选出k个数是的和是sum

2.求最大值最小值

  • 从左上角走到右下角路径的最大数字和
  • 最长上升子序列长度

3.求存在性

  • 取石子游戏,先手是否必胜
  • 能不能选出k个数使得和是sum

题目一

leecode 10. 正则表达式匹 配

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

'.' 匹配任意单个字符

'*' 匹配零个或多个前面的那一个元素

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

示例 1:

输入:s = "aab" p = "cab"

输出:true

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

示例 2:

输入:s = "mississippi" p = "misisp*."

输出:false

解释:第二个*不能匹配si

2.1. 动态规划组成部分1:确定状 态

wc,你倒是说说怎么确定要用动态规划来做啊?

  • 看题目,需要逐步匹配
  • 没有时间复杂度空间复杂度限制,你可以选择>On的
  • 跟前面题很类似,这里需要考虑* 和 .的情况。
  • 尝试根据步骤写出转移方程

在这道题中,我们定义f[i][j] 表示字符串 s 的前 i 个字符与 字符串p的前 j 个字符是否匹配

解动态规划需要两个意识:

  • 最后一步
  • 子问题

最后一步

我们用示例来讲解 :s = "aaab" p = "aa*b"

根据题目意思,我们知道s要被全匹配,我们直接用s去匹配p字符串的每一个字符,这样我们的最后一步就是用s字符串中的b字符去匹配p字符串的每一个字符,匹配最后一个字符为b是否相等。

子问题

有几种情况需要讨论,也就是用s去匹配p最后一个匹配的字符j

  • 如果都是字符,只需要判断:f[i][j] = f[i-1][j-1]

  • 如果是“.” ,说明可以匹配s的最后任意一个字符,也只需:

    f[i][j] = f[i-1][j-1]

  • 如果是“*” ,分两种情况一种是匹配零个字符,一种是匹配1个或多个字符

    如果是匹配零个字符 :f[i][j] = f[i][j-2] ,因为如果j是*,我们就可以对p的j-1匹配任意次数,当然零次就是j-2了。

​ 如果是匹配1个或多个字符:f[i][j] = f[i-1][j],匹配 s 末尾的一个字符,将该字符扔掉,而该组合还可以继续进行匹配,简单点说,零个我们判定了,如果是一个我们扔掉一个字符,如果能匹配则保存,如果匹配两个,我们是知道匹配s的上一个字符的结果的,直接匹配就行,同样匹配多个也是如此。(匹配多个是根据前一个的匹配结果得出来的)

2.2. 动态规划组成部分2:转移方程

在子问题中我们分析的几种情况就是转移方程

2.3. 动态规划组成部分3 :**初始条件和边界情况

因为要涉及到i-1和j-1,注意边界

boolean[][] f = new boolean[m + 1][n + 1];

f[0][0]=true

2.4. 动态规划组成部分4:计算顺序

用 s 去匹配p字符串的每一个字符

它的时间复杂度是 Onm ,由于是二维数据空间复杂度是 Onm

参考代码

public boolean isMatch(String s, String p) {
    int m = s.length();
    int n = p.length();

    boolean[][] f = new boolean[m + 1][n + 1];
    f[0][0] = true;
    for (int i = 0; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (p.charAt(j - 1) == '*') {
                f[i][j] = f[i][j - 2];
                if (matches(s, p, i, j - 1)) {
                    f[i][j] = f[i][j] || f[i - 1][j];
                }
            } else {
                if (matches(s, p, i, j)) {
                    f[i][j] = f[i - 1][j - 1];
                }
            }
        }
    }
    return f[m][n];
}

public boolean matches(String s, String p, int i, int j) {
    if (i == 0) {
        return false;
    }
    if (p.charAt(j - 1) == '.') {
        return true;
    }
    return s.charAt(i - 1) == p.charAt(j - 1);
}
@Test
public void isisMatch() {
     boolean i = isMatch("aa", "a*");
     Assert.assertNotNull(i);
}

真心感谢帅逼靓女们能看到这里,如果这个文章写得还不错,觉得有点东西的话

求不点赞👍 求不关注❤️ 求不分享👥

如果本篇博客有任何错误,请批评指教,不胜感激 !❤️❤️❤️❤️