LeetCode Regular Expression Matching(动态规划)

传送门

题意:

给你两个字符串s和p,让你判断两个字符串是否可以完全匹配.
匹配采用正则化匹配的方式,’.‘可以匹配任意字符,’*'表示前面的一个字符匹配0次或多次.

思路:

比较好想的一种方法就是递归.
首先p中若没有’.‘和’’,那么只需要看s和p是否完全一样即可.
其次若p中有’.‘那么只需要跳过s中和p的’.‘对应的字符,往后继续判断即可
最后若p中有’
'那么它可以使它前面的字符匹配0次或者多次,这种情况我们比较好用递归来解决,也就是让其匹配0次和1次进行递归,就会出现匹配多次的情况.

class Solution:
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        if not p:
        	return not s
        first_match = bool(s) and p[0] in {s[0],'.'}
        if len(p) >= 2 and p[1] == '*':
        	return (self.isMatch(s,p[2:])) or first_match and self.isMatch(s[1:],p)
        else:
        	return first_match and self.isMatch(s[1:],p[1:])

另一种方法就是动态规划(dp),我们发现按照上面我们递归的方法,我们的当前状态都是和后一步的是否匹配状态有关的.所以我们可以设dp(i,j)表示s[i:]和p[j:]是否匹配,这样就会减少很多不必要的递归.

class Solution:
    def isMatch(self, s, p):
    	mem = {}
    	def dp(i,j):
    		if (i,j) not in mem:
	    		if j == len(p):
	    			ans = i == len(s)
	    		else:
	    			match = i < len(s) and p[j] in {s[i],'.'}
		    		if j + 1 < len(p) and p[j + 1] == "*":
		    			ans = dp(i,j + 2) or (match and dp(i + 1,j))
		    		else:
		    			ans =  match and dp(i + 1,j + 1)
    			mem[i,j] = ans
    		return mem[i,j]
    	return dp(0,0)

动态规划的另一种写法.这个方法还是按照动态规划的思路,这里dp(i,j)我们表示s[:i]和p[:j]是否匹配,则:
if p[j-1]为’.'或a-z:
d p [ i ] [ j ] = d p [ i − 1 ] ] [ j − 1 ] dp[i][j] = dp[i-1]][j-1] dp[i][j]=dp[i1]][j1]如果 s [ i − 1 ] = = p [ j − 1 ] s[i - 1] == p[j - 1] s[i1]==p[j1]
else:
if d p [ i ] [ j ] = d p [ i ] [ j − 2 ] dp[i][j] = dp[i ][j - 2] dp[i][j]=dp[i][j2] 如果 p [ j − 2 ] ! = s [ i − 1 ] p[j - 2] != s[i - 1] p[j2]!=s[i1]
else
d p [ i ] [ j ] = = d p [ i ] [ j − 2 ] dp[i][j] == dp[i][j-2] dp[i][j]==dp[i][j2] 这个代表匹配0次
d p [ i ] [ j ] = = d p [ i ] [ j − 1 ] dp[i][j] == dp[i][j-1] dp[i][j]==dp[i][j1] 这个代表匹配1次
d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j] = dp[i-1][j] dp[i][j]=dp[i1][j] 这个代表匹配多次

class Solution:
    def isMatch(self, s, p):
    	dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
    	dp[0][0] = True
    	for i in range(1,len(p) + 1):
    		if p[i - 1] == "*":
    			dp[0][i] = dp[0][i - 2]
    	for i in range(1,len(s) + 1):
    		for j in range(1,len(p) + 1):
    			match = p[j - 1] in {s[i - 1],'.'}
    			if match:
    				dp[i][j] = dp[i- 1][j - 1]
    			elif j != 1 and p[j - 1] == '*':
    				if p[j - 2] not in {s[i - 1],'.'}:
    					dp[i][j] = dp[i][j] or dp[i][j - 2]
    				else:
    					dp[i][j] = dp[i][j] or dp[i - 1][j] or dp[i][j - 2] or dp[i][j - 1]
    	return dp[len(s)][len(p)]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Marcus-Bao

万水千山总是情,只给五角行不行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值