《剑指 Offer》(第 2 版)第 19 题:正则表达式匹配

同 LeetCode 第 10 题,传送门:10. 正则表达式匹配。


小 Fu:视频讲解。

Java 写法:

image-20190124231323024

Python 写法:

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        n = len(s)
        m = len(p)

        dp = [[False for _ in range(m + 1)] for _ in range(n + 1)]

        # 当 s 和 p 的长度都为 0 的时候,定义成匹配
        dp[0][0] = True

        # 处理一种特例
        for i in range(2, m + 1):
            if p[i - 1] == '*' and dp[0][i - 2]:
                dp[0][i] = True

        for i in range(1, n + 1):
            for j in range(1, m + 1):
                if s[i - 1] == p[j - 1] or p[j - 1] == '.':
                    dp[i][j] = dp[i - 1][j - 1]
                elif p[j - 1] == '*':
                    # 这是最麻烦的情况
                    if p[j - 2] != s[i - 1] and p[j - 2] != '.':
                        dp[i][j] = dp[i][j - 2]
                    else:
                        dp[i][j] = dp[i][j - 2] or dp[i][j - 1] or dp[i - 1][j]
        return dp[n][m]

参考资料:http://www.voidcn.com/article/p-zioiffqq-mm.html


“大雪菜”的思路:

思路分析:动态规划,时间复杂度为 。

状态表示:f[i][j] 表示 pj 开始到结尾,是否能匹配 si 开始到结尾。
状态转移:

(关键看后面一个字符,所以,动态规划,从后向前做)

1、如果 p[j+1] 不是通配符 '*',则 f[i][j] 是真,当且仅当 s[i] 可以和 p[j] 匹配,且 f[i+1][j+1]是真;

说明:这一点比价好理解。

2、如果 p[j+1] 是通配符 '*',则下面的情况只要有一种满足,f[i][j] 就是真;
(1)f[i][j+2] 是真;
(2)s[i] 可以和 p[j] 匹配,且 f[i+1][j] 是真;
第 种情况下的状态转移很好理解,那第 种情况下的状态转移怎么理解呢?

最直观的转移方式是这样的:枚举通配符 '*' 可以匹配多少个 p[j],只要有一种情况可以匹配,则 f[i][j] 就是真;
这样做的话,我们发现,f[i][j] 除了枚举 个 p[j] 之外,其余的枚举操作都包含在 f[i+1][j] 中了,所以我们只需判断
f[i+1][j] 是否为真,以及 s[i] 是否可以和 p[j] 匹配即可。

时间复杂度分析: 表示 的长度, 表示 的长度,总共 个状态,状态转移复杂度 ,所以总时间复杂度是 。

Python 写法:

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """

        n = len(s)
        m = len(p)
        f = [[-1 for _ in range(m + 1)] for _ in range(n + 1)]

        return self.dp(0, 0, s, p, f, n, m)

    def dp(self, x, y, s, p, f, n, m):

        if f[x][y] != -1:
            return f[x][y]
        if y == m:
            # 如果模式串用完了,看看字符串是不是也用完了
            f[x][y] = (x == n)
            return f[x][y]
        first_match = x < n and (s[x] == p[y] or p[y] == '.')

        if y + 1 < m and p[y + 1] == '*':
            res = self.dp(x, y + 2, s, p, f, n, m) or self.dp(x + 1, y, s, p, f, n, m)
        else:
            res = first_match and self.dp(x + 1, y + 1, s, p, f, n, m)

        f[x][y] = res
        return f[x][y]

(完)

你可能感兴趣的:(《剑指 Offer》(第 2 版)第 19 题:正则表达式匹配)