给你一个字符串 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
题目标签:String / Dynamic Programming / Backtracking
题目链接:LeetCode / LeetCode中国
这个似乎是剑指Offer上的题目,意在考查正则表达式的实现。
第一次做这个题目花了好几个小时的时间,没办法,比较菜。
最开始的思路是扫描s和p,结果发现可能性实在太多了,if else嵌套了很多,剪不断理还乱,放弃。
然后想到可以把p解析成 (字符, 最少出现次数, 最大出现次数) ,把s解析成 (字符, 出现次数),然后进行比对,但是这种方案依然存在诸多问题,主要是*
究竟要匹配多长。
后来想着,能不能通过递归的方式求解,于是,考虑把问题进行分解,终于写成了一版AC的代码。不过,由于存在大量重复计算,耗时较长。
Language | Runtime | Memory |
---|---|---|
java | 55 ms | 42.1 MB |
class Solution {
public boolean isMatch(String s, String p) {
if (p.isEmpty()) return s.isEmpty();
boolean first_match = !s.isEmpty() && (p.charAt(0) == '.' || (s.charAt(0) == p.charAt(0)));
if (p.length() >= 2 && p.charAt(1) == '*') {
return isMatch(s, p.substring(2)) || (first_match && isMatch(s.substring(1), p));
} else {
return first_match && isMatch(s.substring(1), p.substring(1));
}
}
}
/*
"aa"
"a"
"aa"
"a*"
"ab"
".*"
"aab"
"c*a*b"
"mississippi"
"mis*is*p*."
"a"
".*..a*"
*/
Language | Runtime | Memory |
---|---|---|
cpp | 120 ms | N/A |
class Solution {
public:
bool isMatch(string s, string p) {
// cout << s << ", " << p << endl;
if(s == p){
return true;
}
if(p.length() == 0){
return s == "";
}
if(p.length() == 1){
return s.length() == 1 && (p.at(0) == '.' || p.at(0) == s.at(0));
}
if(p.length() == 2){
if(p.at(1) == '*'){
if(p.at(0) == '.'){ // .*
return true;
}else{ // a*
for(char c : s){
if(c != p.at(0)){
return false;
}
}
return true;
}
}else{ // ab
if(s.length() == 2){
return isMatch(s.substr(0, 1), p.substr(0, 1)) && isMatch(s.substr(1, 1), p.substr(1, 1));
}else{
return false;
}
}
}
if(p.length() > 2){
if(p.at(1) == '*'){ // a*b .*b a*.*b .*bcd
size_t i = 0;
while(i <= s.length()){
if(isMatch(s.substr(0, i), p.substr(0, 2)) && isMatch(s.substr(i, s.length()-i), p.substr(2, p.length()-2))){
return true;
}
i++;
}
return false;
}else{ // abc abcd abc* ab.* b.* b.*ac
return (isMatch(s.substr(0, 1), p.substr(0, 1)) && isMatch(s.substr(1, s.length()-1), p.substr(1, p.length()-1))) || (isMatch(s.substr(0, 2), p.substr(0, 2)) && isMatch(s.substr(2, s.length()-2), p.substr(2, p.length()-2)));
}
}
}
};