「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战」
题目
- 题目来源: 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
解释:".*"表示可匹配零个或多个('')任意字符('.')。
解析
首先读完题目,可以发现这是一道比较明显的动态规划题目,但本题目的状态转移方程的确有几分难想,接下来咱们来一起捋一下
明确 dp[i][j] 代表什么
dp[i][j]: 表示字符串s的前 i 个字符和字符串 p 的前 j 个字符是否匹配,结果为 布尔类型
分析状态转移
对于字符串 p ,有三种可能:
- 小写字母: 由于是小写字母,因此只需判断 s[i] 与 p[j] 是否相等即可
- 若 s[i] == p[j] ,dp[i][j] = dp[i - 1][j - 1]
- 若 s[i] != p[j] ,dp[i][j] = false
- 点号
.:可以匹配任一字符,dp[i][j] = dp[i - 1][j - 1]; - 星号
*
星号比较难处理,咱们单独拉出来
- 分析星号情况
星号的意思是可以匹配0次或者多次
-
s[i]与p[j-1]不匹配: 对于不匹配来说,应当满足下面条件,s[i] != p[j-1] 和 p[j-1] != '.', 此时 dp[i][j] = dp[i][j - 2]
-
s[i]与p[j-1]匹配: 有两种情况,可以是匹配多次(dp[i][j] = dp[i-1][j]),也可能是匹配一次(dp[i][j] = dp[i][j-1]),但是匹配多次情况是包括匹配一次的。
下面举个栗子来深入说明一下这点:
s = “afs”,p = "afs*"
匹配多次:dp[3][4] = dp[2][4]
匹配一次:dp[3][4] = dp[3][3]
其实结果上是一样的,都是true,只不过这里dp[2][4]表示不使用"s*"时,s与p匹配,而dp[3][3]是直接匹配。
所以由上我们得到此种情况下的结论:dp[i][j] = dp[i-1][j]?
和不匹配时相同,上面这样分析,我们又漏掉了 p[j-1] = '.' 的情况,下面再举个例子
s = "ab",p = "ab.*",
dp[2][4]应该是true,但是按照上面的写法的话dp[2][4] = dp[1][4]就是false,这里应该匹配零次".*",即:dp[2][4] = dp[2][2]。
因此,正确的结论是:dp[i][j] = dp[i-1][j] || dp[i][j - 2];
边界情况
- dp[0][0] = true;
- dp[i][0] = false; (i > 0)
- dp[0][j](j > 0)可能为true
总结
分析完上面部分,其实整个题目的脉络就很清晰了,只需要将上面的分析过程翻译成代码。
往期精彩文章
- 牛客最新前端JS笔试百题
- 牛客最新前端面经面试题汇总(含解析)
- 抓取牛客最新前端面试题五百道 数据分析JS面试热点
- 给VSCode和网站领养喵咪 一起快乐撸猫
- 原生JavaScript灵魂拷问(一),你能答上多少?
- JavaScript之彻底理解原型与原型链
- JavaScript之彻底理解EventLoop
- 《2w字大章 38道面试题》彻底理清JS中this指向问题
后语
伙伴们,如果大家感觉本文对你有一些帮助,给阿包点一个赞👍或者关注➕都是对我最大的支持。
另外如果本文章有问题,或者对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!
如果感觉评论区说不明白,也可以添加我的微信(li444186976)或者 qq(3315161861) 详细交流,名字都是战场小包。