正则表达式
10. 正则表达式匹配
难度困难
给你一个字符串 s
和一个字符规律 p
,请你来实现一个支持 ‘.‘
和 ‘*‘
的正则表达式匹配。
‘.‘ 匹配任意单个字符 ‘*‘ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s
的,而不是部分字符串。
说明:
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母,以及字符.
和*
。
示例 1:
输入: s = "aa" p = "a" 输出: false 解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入: s = "aa" p = "a*" 输出: true 解释: 因为 ‘*‘ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a‘。因此,字符串 "aa" 可被视为 ‘a‘ 重复了一次。
示例 3:
输入: s = "ab" p = ".*" 输出: true 解释: ".*" 表示可匹配零个或多个(‘*‘)任意字符(‘.‘)。
示例 4:
输入: s = "aab" p = "c*a*b" 输出: true 解释: 因为 ‘*‘ 表示零个或多个,这里 ‘c‘ 为 0 个, ‘a‘ 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入: s = "mississippi" p = "mis*is*p*." 输出: false--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------解答:这个题规则有点儿多,需要先理清思路:问题一,用递归应该怎么递归?1.应为题目给的字符串有S和P其中S中全是普通字符串,P作为匹配字符串里面有特殊字符。2.按照P中出现的字符串是不是*好分类,并分别写出递归式: 1)不是*号(是普通字符) 此时比较简单 dp[i][j] = dp[i-1][j-1] s[i-1]==p[j-1]; dp[i][j] = false s[i-1]!=p[j-1]; 解释:因为当前出现的是普通字符,那么它与当前这个字符能不能匹配的必要条件是s[i]==p[j], 如果这个条件不满足那么一定匹配不上,满足后还要看前一个是不是能匹配上,前一个能匹配上 那么一定是可以的,如果前一个没匹配上那一定不行。 2)是*号 这个时候要复杂点儿。首先考虑到*号的用途有*好的所有情况分类。 1)一定要将前一个抵消才可能满足。意思就是将前一个给废了才可能满足,这个时候是什么情况呢? 这个时候就是p[j-2]!=s[i-1]这样*好智能不代表前面一个才有可能,此时的动态规划式是: dp[i][j] = dp[i][j-2] p[j-2]!=s[i-1]; 2)不将*号的前一个给废了也可能匹配到所有的字符。 dp[i][j] = dp[i][j-2] or dp[i][j-1] or dp[i-1][j] p[j-2]!=s[i-1]; 分别对应将前一个销毁,一个前一个,两个以上前一个。 这个逻辑不是很完备,因为这里仅仅只 考虑到满足情况的时候一定是对的,但是当不满足情况时会不会被误判为对呢? 只能说有可能,但是分析起来异常困难,这里就不做分析,到时候出了问题再来调。
3)边界条件,按照以上两点分类,在一般的情况下是全部都分类完了,不存在分类的不完全和交叉。。但是没有考虑边界情况 1)对1)中,如果s或者p中是第一个元素怎么办,这时候前面一个元素是没有的。 这时候需要考察一下这个空的意义,空就是所有的匹配到那儿啥也没有了,比如s为空 p为空 那肯定能匹上。 S为空p不为空,那证明p中全部都该消失,形如:a*b*.啥也没有。 按照以上逻辑就能解决这个问题。 2)对2) 中,如果j-2<0 or j-1<0 or i-1<0 呢? 这个其实很简单 : 思路就是 : 既然不存在 那就不称其为证据。也就是false.总结:考虑每种情况的实际意义,在这个意义下再来同一安排,只要是在同一的意义下,且每个值都是对的,那么在这个意义下递推公式得到的结果就是对的。以上就应该考虑空对应的意义。要不然就只有反复补漏就很烦。