描述
该题来自于力扣第10题
给你一个字符串s
和一个字符规律p
,请你来实现一个支持'.'
和'*'
的正则表达式匹配。
'.'
匹配任意单个字符
'*'
匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖整个字符串s
的,而不是部分字符串。
示例 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
提示:
0 <= s.length <= 20
0 <= p.length <= 30
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母,以及字符.
和*
。- 保证每次出现字符
*
时,前面都匹配到有效的字符
分析
- 该题可以采用状态机来解,类似的已在leetcode题解8中介绍了;该题还有其他解法——动态规划,用
dp[i][j]
来表示s
的前i
个字符与p
的前j
个字符是否匹配,那么可以注意到: - 先不考虑
*
,如果p[j]
与s[i]
匹配到了,即要么s[i]=p[j]
,要么p[j]='.'
,那么dp[i][j]=dp[i-1][j-1]
,否则就为false
- 再考虑
*
,即如果p[j]='*'
- 如果
s[i]
与p[j-1]
匹配- 则
*
前面的字符p[j-1]
可能匹配s
中多个,比如s=aaa
,p=a*
,这时dp[i][j]=dp[i-1][j]
- 也可能
*
前面的字符不匹配s
中的字符,比如s=aa
,p=aaa*
,这时dp[i][j]=dp[i][j-2]
- 则
- 如果
s[i]
与p[j-1]
不匹配,那么*
前面的字符不匹配s
中的字符,这时dp[i][j]=dp[i][j-2]
- 如果
算法
根据前面分析知道,麻烦在于p[j]='*'
时的处理,实际上无论s[i]
与p[j-1]
是否匹配到了,*
前面的字符都可能不匹配s
中的字符,也就是说dp[i][j] = dp[i][j-2]
或者dp[i][j] = dp[i][j-2] | dp[i-1][j]
;
所以实现的时候可以让dp[i][j]
初始化为false
,按照dp[i][j]
的定义,i,j
都必须大于0,这时可以让dp[i][j]
表示两个空字符串是否匹配,当然设为true
了,最后按照方程进行状态转移就可以了
代码
python3
1 | class Solution: |
c++
1 | class Solution { |
java
1 | class Solution { |