前言
是本篇博客主要记录和复习,在LeetCode上刷到的这道题,很有意思!不过,什么都需要耐心和细心去解决。
提示:以下是本篇文章正文内容,下面案例可供参考
一、问题描述
请实现一个函数用来匹配包含 ’ . ’ 和 ’ * ’ 的正则表达式。模式中的字符 ’ . ’ 表 示任意一个字符,而 ’ * ’ 表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串 “aaa” 与模式 “a.a” 和 " ab * ac * a" 匹配,但与 “aa.a” 和 “ab*a” 均不匹配。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof
二、解题思路及代码
1.解题思路
假设两个字符串分别为s和p,固定s判断p,分别判断第i、j位,一共有三种情况:
(1)s和p都为空,则返回True;s或p为空,返回False;
(2)判断 ’ . ‘ 存在的情况,这个还是比较简单的,它是万能字符嘛,可以替代任意,所以如果 p的我最后一位 p[j-1] 出现 ’ . ’ 时,直接继承前一位 p[j-2] 的判断结果;
(3)判断 ‘ * ’ 存在的情况,这个就比较复杂了,因为星号可以湮灭前面的字符,亦可以复制前面的字符,所以该怎么办呢?再分两种情况:(i)湮灭其前面 p[j-2] 的字符,直接往前两位,继承 p[j-3] 的判断结果;(ii)不淹灭的话,则先判断 p[j-2] 的数字,s[i-1]==p[j-2] 或 p[j-2] == ’ . ’ 时,继承 s[i-2] 与p[j-1] 的判断结果。
这样说肯定很不明白,来看下面的三幅图,说明一下(3)的几种情况,首先建立一个表格,表格的大小为m * n,其中m、n分别为s和p的长度
图1 只有 湮灭起作用
图2 湮灭 + 辅助继承 起作用
2.程序及注释
代码如下(示例):
class Solution:
def isMatch(self, s: str, p: str) -> bool:
#调用官方函数 不为null 返回True
# return (re.fullmatch(p,s)) != None
#自己编写一下啊
#定义两个字符串的长度
m,n = len(s),len(p)
#固定s匹配p
#建立m*n的判断表
dp = [[False for j in range(n+1)] for i in range(m+1)]
for i in range(m+1):
for j in range(n+1):
#p为空的情况
if j == 0:
if i == 0:dp[i][j] = True
else:
#p不为空 且p[j-1] 不为 *
if p[j-1] != '*':
#s字符必须有东西 匹配的条件有两种如下所示 s与p相等 要不 p为万能'.'
if i > 0 and (s[i-1] == p[j-1] or p[j-1] == '.'):
dp[i][j] = dp[i-1][j-1]
else:
# * 号大法湮灭p[j-2] p序列末尾变为j-3
# 那么我所判断dp[i][j]就转变为dp[i][j-2]的判断
if j > 1:
#考虑到下面还有一种情况 因此这里要使用 |= 按位或的情况
dp[i][j] |= dp[i][j-2]
if (i > 0 and j > 1) and (s[i-1] == p[j-2] or p[j-2] == '.'):
dp[i][j] |= dp[i-1][j]
return dp[i][j]
原来的代码不对,现在已经更正!建表没搞好,第一个中括号里面是列,第二个中括号里面是行,所以应该是:
dp = [[False for i in range(n+1)] for j in range(m+1)]
三、总结
这道题其实挺有意思的,花费的时间挺长,确实不好理解,不过仔细想想,也是一种穷举判断的方法,细心一点,多思考还是可以搞出来的!ha ha ~