10. 正则表达式匹配
本文最后更新于:25 天前
10. 正则表达式匹配
题目描述
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。
- ‘.’ 匹配任意单个字符
- ‘*’ 匹配零个或多个前面的那一个元素
- 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
示例 1:
1 |
|
示例 2:
1 |
|
示例 3:
1 |
|
提示:
- 1 <= s.length <= 20
- 1 <= p.length <= 20
- s 只包含从 a-z 的小写字母。
- p 只包含从 a-z 的小写字母,以及字符 . 和 *。
- 保证每次出现字符 * 时,前面都匹配到有效的字符
题解
解法一:动态规划
以下题解思路和图片,引用自:
作者:笨猪爆破组
从左往右扫的话
- 字符后面是否跟着星号会影响结果,分析起来有点复杂。
选择从右往左扫描
星号的前面肯定有一个字符,星号也只影响这一个字符,它就像一个拷贝器。
s、p 串是否匹配,取决于:最右端是否匹配、剩余的子串是否匹配。
只是最右端可能是特殊符号,需要分情况讨论而已。
通用地表示出子问题
- 大子串是否匹配,和剩余子串是否匹配,是规模不一样的同一问题。
情况1:s[i−1] 和 p[j−1] 是匹配的
- 最右端的字符是匹配的,那么,大问题的答案 = 剩余子串是否匹配。
情况2:s[i−1] 和 p[j−1] 是不匹配的
- 右端不匹配,还不能判死刑——可能是 p[j−1] 为星号造成的不匹配,星号不是真实字符,它不匹配不算数。
- 如果 p[j−1]p[j-1]p[j−1] 不是星号,那就真的不匹配了。
- p[j−1]==”∗”,且 s[i−1] 和 p[j−2] 匹配
- p[j−1] 是星号,并且 s[i−1] 和 p[j−2] 匹配,要考虑三种情况:
- p[j−1] 星号可以让 p[j−2] 在 p 串中消失、出现 1 次、出现 >=2 次。
- 只要其中一种使得剩余子串能匹配,那就能匹配,见下图 a1、a2、a3。
- a3 情况:假设 s 的右端是一个 a,p 的右端是 a * ,* 让 a 重复 >= 2 次
- 星号不是真实字符,s、p是否匹配,要看 s 去掉末尾的 a,p 去掉末尾一个 a,剩下的是否匹配。
- 星号拷贝了 >=2 个 a,拿掉一个,剩下 >=1 个a,p 末端依旧是 a* 没变。
- s 末尾的 a 被抵消了,继续考察 s(0,i-2) 和 p(0,i-1) 是否匹配。
- p[j−1] 是星号,并且 s[i−1] 和 p[j−2] 匹配,要考虑三种情况:
- p[j−1]==”∗”,但 s[i−1] 和 p[j−2] 不匹配
- s[i−1] 和 p[j−2] 不匹配,还有救,p[j−1] 星号可以干掉 p[j−2],继续考察 s(0,i−1) 和 p(0,j−3)。
- s[i−1] 和 p[j−2] 不匹配,还有救,p[j−1] 星号可以干掉 p[j−2],继续考察 s(0,i−1) 和 p(0,j−3)。
base case
- p 为空串,s 不为空串,肯定不匹配。
- s 为空串,但 p 不为空串,要想匹配,只可能是右端是星号,它干掉一个字符后,把 p 变为空串。
- s、p 都为空串,肯定匹配。
代码实现
1 |
|
总结
- 逆序思考问题,从右往左扫描,可以简化问题;
- 状态转移方程的推导,需要考虑多种情况,包括星号的作用;
- 边界条件的处理,需要考虑 s、p 为空串的情况;
10. 正则表达式匹配
https://ccccx159.github.io/2024/04/14/leetcode/10.正则表达式匹配/