6.21 - hard - 2

10. Regular Expression Matching
dp问题是先找到状态,这一步我找出来了,然后要初始化,我没考虑到下面提到的corner case,然后要写出递推公式,我写出了 p[i] != "*"的情况,然后就不会了。。。研究了一个答案,虽然明白了,但是感觉如果再换一种方式来问,我还是不太能答出来这个问题。也没什么其它办法,估计只能多写两遍,增加对这种题型的感觉和熟练度。

class Solution(object):
    def isMatch(self, s, p):
        # The DP table and the string s and p use the same indexes i and j, but
        # table[i][j] means the match status between p[:i] and s[:j], i.e.
        # table[0][0] means the match status of two empty strings, and
        # table[1][1] means the match status of p[0] and s[0]. Therefore, when
        # refering to the i-th and the j-th characters of p and s for updating
        # table[i][j], we use p[i - 1] and s[j - 1].

        # Initialize the table with False. The first row is satisfied.
        table = [[False] * (len(s) + 1) for _ in range(len(p) + 1)]

        # Update the corner case of matching two empty strings.
        table[0][0] = True

        # Update the corner case of when s is an empty string but p is not.
        # Since each '*' can eliminate the charter before it, the table is
        # vertically updated by the one before previous. [test_symbol_0]
        # 也就是说对于某一个i也就是p[:i]匹配与空串""等于当p[i-1]是为*,p[:i-2]匹配与空串
        # 例子 p = "a*b*" p[:4] 匹配与""就等于 p[3] == "*" and p[:2]匹配与空串结果为True 
        for i in range(2, len(p) + 1):
            table[i][0] = table[i - 2][0] and p[i - 1] == '*'

        for i in range(1, len(p) + 1):
            for j in range(1, len(s) + 1):
                if p[i - 1] != "*":
                    # Update the table by referring the diagonal element.
                    # 这个好理解,如果当前p值不为*,那么当前的值就等于之前的值and一些当前条件
                    table[i][j] = table[i - 1][j - 1] and (p[i - 1] == s[j - 1] or p[i - 1] == '.')
                else:
                    # 当此时的字符为*时候,则分为两种情况
                    # Eliminations (referring to the vertical element)
                    # Either refer to the one before previous or the previous.
                    # I.e. * eliminate the previous or count the previous.
                    # [test_symbol_1]
                    # 第一种情况是*代表之前的0个字符,或者代表之前的1个字符
                    # 也就是看看当前的s[:j]是否匹配与 p[:i-1]或者p[:i-2]
                    table[i][j] = table[i - 2][j] or table[i - 1][j]
                    
                    # Propagations (referring to the horizontal element)
                    # If p's previous one is equal to the current s, with
                    # helps of *, the status can be propagated from the left.
                    # [test_symbol_2]
                    # 第二种情况*是扩充了当前的字符
                    # 也就是说如果s[j-1]也就是当前考虑的字符和p[i-2]也就是*之前的字符相同
                    # 或者p[i-2]也就是*之前的字符为"."那么可以用当前的匹配 or p[:i] 和 s[:j-1]的匹配
                    # 例如 p = "ab*" s = "abbbb"
                    # p[:3] 和 s[:4] 也就是abbb匹配时,因为p[2] = "*" p[1] == s[3]
                    # 所以 p[:3]和s[:4]的匹配就相当于 or 上 p[:3]和s[:3]的匹配,因为后一位可以由*扩展而来
                    if p[i - 2] == s[j - 1] or p[i - 2] == '.':
                        table[i][j] |= table[i][j - 1]

        return table[-1][-1]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,767评论 0 33
  • 每天总结hard20题,三段总解法:1. 找个比较规范的答案,2.把每一行的思路写下来,3.删掉答案重写一遍。不过...
    健时总向乱中忙阅读 180评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,845评论 18 139
  • 思考扺不过肚皮。没等我理顺这乱糟糟的脑子,它就发出了抗议。雨到底是没有下,可整个天却愁着个脸。必须找点什么撑一下,...
    山水我心阅读 216评论 0 0
  • 为UITextField 添加分类属性 .h .m
    zcaaron阅读 312评论 0 1