10_Regular_Expression_Matching 正
题目描述
给你一个字符串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
解法一:递归
#include <string>
#include <iostream>
using namespace std;
bool isMatch(string s, string p) {
//p为空
if (p.empty()) {
return s.empty();
}
bool first_match = !s.empty() && (s[0] == p[0] || p[0] == '.');
//只有p长度>=2的时候,才考虑*的存在
if (p.size() >= 2) {
if (p[1] == '*') {
//两种情况, 1.pattern修改,直接跳过两个字符,表示*前面字符出现了0次
// 2. pattern不变,表示*用前一个字符替代(代码实现上无需真的replace *, 而是p右移一位即可有该效果,你体会一下)
return isMatch(s, p.substr(2)) || (first_match && isMatch(s.substr(1), p));
} else {
return first_match && isMatch(s.substr(1), p.substr(1));
}
} else { //p长度为1
return (s.size() == 1) && (s == p || p == ".");
}
}
int main() {
string s = "a";
string p = "a";
cout << isMatch(s,p) << endl;
}
思路
看代码注释就很容易明白思路了,在这还是简单说一下吧。
遇到这种问题,需要找规律的,就按长度从小到大考虑----渐进!
你看题目给的几个case顺序都是长度从小到大的,很贴心了。
这个题的难点就在于*
的存在,它可以让前面的字符出现0次或者多次。
注意*
不能出现在第一位,因为它前面没字符,所以没意义。因此只有长度>=2时,才考虑*
。
if p为空,那么s为空 true; s不空 false。
if p长度为1 那么s长度为1 && (s==p || p == '.')才返回true; 否则返回false。
if p长度>=2,这时需要考虑*的存在了。
- p[1] == '*'的情况
- pattern直接跳过两个字符,表示
*
前面的字符出现0次。
例如s="aab"
,p="c*a*b"
的情况,需要直接跳过c*
, 假装p是"a*b"
然后去和s匹配。
或 - pattern不变,表示*用前一个字符替代。
例如s="aa"
,p="a*"
,在这里*
被a
替代,p="aa"
去和s
匹配。实现上有个trick,就是不需要真的replace*
,只需将p右移一位即可。
- pattern直接跳过两个字符,表示
- p[1] !=
'*'
的情况
那么return first_match && isMatch(s,substr(1), p.substr(1))
理清了上述规律,下面找个case来模拟一下匹配过程。
-
s="aab"
,p="c*a*b"
isMatch(s,p) = isMatch("aab"
,"a*b"
) = isMatch("aab"
,"aab"
) = true -
s="mississippi"
,p="mis*is*p*"
isMatch(s,p) = isMatch("ssissippi"
,"s*is*p*"
) = isMatch("ssissippi"
,"ssis*p*"
) = isMatch("ssippi"
,"s*p*"
) = isMatch("ssippi"
,"ssp*"
) = isMatch("ippi"
,"p*"
) = false