动态规划 | #正则表达式匹配#
正则表达式匹配
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
CVTE公司福利 672人发布