动态规划 | #正则表达式匹配#

正则表达式匹配

https://www.nowcoder.com/practice/28970c15befb4ff3a264189087b99ad4?tpId=13&tqId=1375406&ru=/exam/oj/ta&qru=/ta/coding-interviews/question-ranking&sourceUrl=%2Fexam%2Foj%2Fta%3Fpage%3D1%26tpId%3D13%26type%3D265

class Solution:
    def match(self , str: str, pattern: str) -> bool:
        # write code here
        #######################将*和.或者a-z结合在一起进行分割############################
        self.str = list('aaa'+pattern+'---')  # 序列padding,避免空字符、单字符等特殊情况处理
        self.pattern = list('aaa'+str+'---')
        iii = 0
        while self.str[iii] != '-':
            if self.str[iii+1] == '*':
                self.str[iii] += '*'
                del self.str[iii+1]
            iii += 1
        iii = 0
        while self.pattern[iii] != '-':
            if self.pattern[iii+1] == '*':
                self.pattern[iii] += '*'
                del self.pattern[iii+1]
            iii += 1
        n = len(self.str)
        m = len(self.pattern)


        #######################动态规划求解############################
        dp_arr = [[0 for _ in range(m)] for __ in range(n)]
        dp_arr[0][0] = dp_arr[1][1] = dp_arr[2][2] = 1
        pre_st = 3
        for i in range(2, n):
            cur_st = 2
            if self.str[i] == '.*': # 通配符,直接秒杀这一行,进入下一行
                dp_arr[i][pre_st:] = [1]*(m-pre_st)
                continue
            for j in range(pre_st, m):
                if not (dp_arr[i-1][j] or dp_arr[i-1][j-1] or dp_arr[i][j-1]): break  # 如果↑、↖、←元素都为0,当前元素失去了匹配基础,直接跳到下一行
                # 以下三个if,只要有一个给dp_arr赋1,则不进入下一个if
                if dp_arr[i-1][j]:  # ↑方向已有匹配,新的str[i]要匹配的话只能变成''空字符,也只有带*的字符符合条件
                    dp_arr[i][j] = int('*' in self.str[i])
                if (not dp_arr[i][j]) and dp_arr[i-1][j-1]:  # ↖已有匹配,新的str[i]要匹配的话1、pattern[i]等于str[i],2、等于带星号str[i]的数字部分,3、str[i]为'.'
                    dp_arr[i][j] = int((self.pattern[j] in self.str[i]) or ('.' in self.str[i]))
                if (not dp_arr[i][j]) and dp_arr[i][j-1] and '*' in self.str[i]:  # ←已有匹配,新的str[i]要匹配的话,当前str[i]必须带星号而且pattern[j-1]等于pattern[j]和str[i]的数字部分
                    dp_arr[i][j] = int(self.pattern[j] == self.pattern[j-1] and (self.pattern[j] in self.str[i]))
                if dp_arr[i][j] and cur_st==2:  # 记录当前行第一个变为1的列号,作为下一行的起点,节省时间
                    cur_st = j
            pre_st = cur_st*1

        print(*dp_arr, sep='\n')
        return dp_arr[n-1][m-1]
                
                    

str1 = 'aaa'   
str2 = 'ab*a'     

print(Solution().match(str1, str2))



             

# 动态规划思路

# 1. 构建状态,定义pattern当前元素pattern[i]和str当前元素str[j]是否匹配为当前状态。

# 2. 构造一个n*m的表格,对于某一个状态,是否匹配取决于↑↖←三个相邻表格,状态转移方法如下:

# - ↑已经匹配的话,要匹配当前点,则pattern[i]只能为空字符;

# - ↖已经匹配的话,pattern[i]必须能匹配str[i];

# - ←已经匹配的话,pattern[i]必须是一个char*,且str[j]要等于char。

# 以上三个条件任意满足一个即可,我们不需要关心匹配上的pattern会退化为什么形式(比如A*退化为AAA),因为接下来的匹配不会关心这件事

# 3. 如果最后表格最后一个元素能匹配,返回True

全部评论

相关推荐

11-09 01:22
已编辑
东南大学 Java
高级特工穿山甲:羡慕,我秋招有家企业在茶馆组织线下面试,约我过去“喝茶详谈”😢结果我去了发现原来是人家喝茶我看着
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务