dp动态规划详解--leetCode dp求解正则化匹配

动态规划的重点在于两点:
1、问题可分解成子问题。
2、子问题在后续访问过程中有重复访问的问题。==》可以用空间换时间,建立数组来记录每个子问题的答案结果。
示例:最长递增序列问题。

请添加图片描述

先放一个暴力递归求解的方法

def L(nums,i):
    if i == len(nums)-1:    #结束条件
        return 1

    max_len = 1
    for j in range(i+1,len(nums)):
        if nums[j] > nums[i]:
            max_len = max(max_len,L(nums,j)+1)
    return max_len

def length_of_LIS(nums):
    return max(L(nums,i) for i in range(len(nums)))
    
nums = [1,5,2,4,3]
print(length_of_LIS(nums))

再放一个dp算法求解的方法

#最长递增序列问题

memo = {} #dp数组记录中间过程数据 记忆化搜索 用空间换时间
def L(nums,i):
    #if i == len(nums)-1:    #结束条件,递归算法结束条件判断数组是否已经结束
        #return 1
    if i in memo:    # dp算法的结束条件,判断L子问题是否已经
        return memo[i]

    max_len = 1
    for j in range(i+1,len(nums)):      #从当前点的后一个数开始遍历寻找子解的最长递增序列
        if nums[j] > nums[i]:
            max_len = max(max_len,L(nums,j)+1)  #分两种情况,加入这个元素和不加这个元素取最大
    memo[i] = max_len
    return max_len

def length_of_LIS(nums):
    return max(L(nums,i) for i in range(len(nums)))

nums = [1,5,2,4,3]
print(length_of_LIS(nums))

比较这两个求解方法可以得出,他俩之间的区别只有子问题的答案记录与否。

回到学这个算法的初衷 – 求解正则化匹配问题。

首先也是递归求解匹配问题

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        if(len(p) == 0):    #匹配链为空的时候
            return len(s) == 0
        elif(len(p) == 1):  #匹配链还剩余一个字符
            return ((len(s)==1) and (self.isequal(s[0],p[0])))
        elif(p[1]!='*'):    #匹配链后一个字符是否为* *号要进行多情况考虑,.*分情况进行尝试,1、空匹配,2、多匹配
            return ((not(len(s)==0)) and (self.isequal(s[0],p[0])) and (self.isMatch(s[1:],p[1:])))
        else:   #其余情况,单匹配
            while(((not(len(s)==0)) and (self.isequal(s[0],p[0])))):
                if(self.isMatch(s,p[2:])):
                    return True
                s=s[1:]
            return self.isMatch(s,p[2:])
    def isequal(self, a, b):
        if (a == b):
            return True
        elif (b == '.'):
            return True
        else:
            return False

s = "aab"
p = "c*a*b*"

result = Solution().isMatch(s,p)
print(result)

dp动态规划算法求解

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        #传入两个字符,传回来是否可以匹配
        def match(a, b):
            return a > 0 and s[a] == p[b] or p[b] == '.'
        m, n = len(s), len(p)
        #dp数组
        dp = [[0]*(n+1) for _ in range(m+1)]
        dp[0][0] = 1
        #因为匹配链是一直连续下去的 所以这里的按位或是一种传递手段,只有当前面匹配的时候后面才有可能为1
        #为什么dp数组要比实际的数组大一个数据,免于考虑数据是否超出范围的问题。
        for i in range(m+1):
            for j in range(1, n+1):
                if p[j-1] == '*':
                    dp[i][j] |= dp[i][j-2] #按位或
                    if match(i, j-1):
                        dp[i][j] |= dp[i-1][j]
                else:
                    if match(i, j):
                        dp[i][j] |= dp[i-1][j-1]
        return True if dp[m][n] else False
                
s = "aab"
p = "c*a*b*"

result = Solution().isMatch(s,p)
print(result)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值