题目描述:请实现一个函数用来匹配包含'. '和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"和"ab*a"均不匹配。
分析:
正则,由于匹配是指字符串的所有字符匹配整个模式,所以正则表达式应该将模式串使用 ^ $来限制即可。
递归,
1. 若模式字符串为空,是否匹配取决于原字符串是否为空;
2. 若模式字符串前两个为 字符 x + *,有以下几种情况:
- 匹配字符x 0 次,则是否匹配由 * 后面的子模式决定;
- . 匹配字符x 多次,则由模式字符串中首个字符与字符串中的首个字符是否匹配(即该模式字符为 . 或者两字符相等)且 字符串除首个字符以外的后续字串与模式字符串是否匹配决定;
3. 模式字符串前两个不是字符 x + *时,由模式字符串中首个字符与字符串中的首个字符是否匹配(即该模式字符为 . 或者两字符相等)且字符串除首个字符以外的后续字串与模式字符串除首个字符以外的模式是否匹配决定;
求解:
// 正则
function isMatch1(s: string, p: string): boolean {
return new RegExp(`^${p}$`).test(s);
}
// 递归
function isMatch2(s: string, p: string): boolean {
const pLen = p?.length;
// 模式字符串为空时,如果原字符串空说明匹配,否则不匹配
if (!pLen) return !s;
// 模式字符串为 字符 + * 说明是否匹配可以是以下情况:
// 1. s 与 * 后面的模式是否匹配 (即 字符 + * 匹配 0 次字符)
// 2. 字符相等 或者 模式中为 。且 后续字符匹配
if (p[1] === '*') {
return isMatch2(s, p.substring(2)) || (!!s && (s[0] == p[0] || p[0] == '.') && isMatch2(s.substring(1), p));
}
// 模式字符串为 . 说明无论 s 是多少都匹配,或者 s 与 p 字符相等,说明是否匹配,由后续子串决定
return !!s && (p[0] === '.' || s[0] === p[0]) && isMatch2(s.substring(1), p.substring(1));
}