题目描述
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。
在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
解法一:
这里主要说一下自己的想法吧。
统一假设 * 前面的字符为 pre。
主要分为两种情况,一种 str 为空,一种不为空
- 一. 当 str 为空,只能匹配以下情况,“”、“a*”、“a*b*…”等,所以我认为 pattern 应该为偶数,且每一个字符后面都应该后跟一个 ‘*’, 否则便是错误。(考虑过连续多个 ‘*’ 的出现,即错误判断,但是发现我解决不了)
- 二. 当 str 不为空,由于 ‘*’ 前面的字符可以出现任意次。又可以分两种情况,一种能匹配,一种不能匹配。
-
- 如果不能匹配,100%跳过,出现0次
-
- 如果能匹配,又是两种情况,pre出现0次与多次,例如"a"和"a*", "“和"a*”。我们统一首先假设pre一次不出现(虽然能匹配上),然后递归执行 match() 函数,返回真,则最终返回真;返回假,pre出现次数+1,重复上述过程。直到 str 或者 pattern其中一个遍历完。
- 遍历完还没完事那,还有两种情况。(1)str 遍历完, pattern没遍历完。这时,str 剩余字符为‘\0’,pattern则还有其他剩余字符。执行一次pattern剩余字符的判断,是否符合第一种情况,即第一条。看两个个例子吧:“aaa” 和 “aaa*”, “aaa” 和 “aa*b”。(2)pattern 遍历完,但是 str 没有遍历完,这是肯定错误的。代码超时,自己测了一些感觉没问题。
class Solution {
public:
bool match(char* str, char* pattern)
{
if (*str == '\0')
{
if (*pattern == '\0')
return true;
else
return judge(pattern);
}
int slen = 0, plen = 0;
slen = size(str);
plen = size(pattern);
int sIndex = 0, pIndex = 0;
while (sIndex < slen && pIndex < plen)
{
//遇到*,直接跳过
if (pattern[pIndex + 1] == '*')//'\0'-stop
{
if (pattern[pIndex] != str[sIndex] && pattern[pIndex] != '.')
{
pIndex += 2;
continue;
}
//跳过之后可以匹配
if (pattern[pIndex + 2] == str[sIndex] || pattern[pIndex + 2] == '.')
{
if (match(str + sIndex, pattern + pIndex + 2))//跳过之后完全匹配
return true;
}
else//跳过之后不匹配,那就只能当前匹配
{
//匹配成功
if (pattern[pIndex] == str[sIndex] || pattern[pIndex] == '.')
sIndex++;
else
return false;
}
}
else
{
if (pattern[pIndex] == str[sIndex] || pattern[pIndex] == '.')
{
sIndex++;
pIndex++;
}
else
return false;
}
}
if (sIndex >= slen && pIndex < plen)
return judge(pattern + pIndex);
if (pIndex >= plen && sIndex < slen)
return false;
return true;
}
private:
bool judge(char *pattern)
{
int index = 0;
int plen = 0;
plen = size(pattern);
if (plen % 2 != 0)
return false;
for (index; index < plen; index += 2)
if (pattern[index + 1] != '*')
return false;
return true;
}
int size(char *ch)
{
int length = 0;
for (; *ch != '\0'; ch++) length++;
return length;
}
};
思路比较乱,欢迎指正。
解法二:
这里借用牛客大佬的东西,如果涉及侵权,直接删掉。
哎,情况都考虑到了,就是思路比较复杂,语言表达能力也不行,努力吧。。。
以下来源牛客帖子,链接如下
链接:https://www.nowcoder.com/questionTerminal/45327ae22b7b413ea21df13ee7d6429c
来源:牛客网
/* 解这题需要把题意仔细研究清楚,反正我试了好多次才明白的。 首先,考虑特殊情况: 1>两个字符串都为空,返回true 2>当第一个字符串不空,而第二个字符串空了,返回false(因为这样,就无法 匹配成功了,而如果第一个字符串空了,第二个字符串非空,还是可能匹配成 功的,比如第二个字符串是“a*a*a*a*”,由于‘*’之前的元素可以出现0次, 所以有可能匹配成功) 之后就开始匹配第一个字符,这里有两种可能:匹配成功或匹配失败。但考虑到pattern 下一个字符可能是‘*’, 这里我们分两种情况讨论:pattern下一个字符为‘*’或 不为‘*’: 1>pattern下一个字符不为‘*’:这种情况比较简单,直接匹配当前字符。如果 匹配成功,继续匹配下一个;如果匹配失败,直接返回false。注意这里的 “匹配成功”,除了两个字符相同的情况外,还有一种情况,就是pattern的 当前字符为‘.’,同时str的当前字符不为‘\0’。 2>pattern下一个字符为‘*’时,稍微复杂一些,因为‘*’可以代表0个或多个。 这里把这些情况都考虑到: a>当‘*’匹配0个字符时,str当前字符不变,pattern当前字符后移两位, 跳过这个‘*’符号; b>当‘*’匹配1个或多个时,str当前字符移向下一个,pattern当前字符 不变。(这里匹配1个或多个可以看成一种情况,因为:当匹配一个时, 由于str移到了下一个字符,而pattern字符不变,就回到了上边的情况a; 当匹配多于一个字符时,相当于从str的下一个字符继续开始匹配) 之后再写代码就很简单了。 */
class Solution {
public:
bool match(char* str, char* pattern)
{
if (*str == '\0' && *pattern == '\0')
return true;
if (*str != '\0' && *pattern == '\0')
return false;
if (*(pattern + 1) != '*')
{
if (*pattern == *str || (*str != '\0' && *pattern == '.'))
return match(str+1, pattern + 1);
else
return false;
}
else
{
if (*pattern == *str || (*str != '\0' && *pattern == '.'))
return match(str + 1, pattern) || match(str, pattern + 2);
else
return match(str, pattern + 2);
}
}
};
总结(自己看):看完思路之后,自己写了下代码,漏了判断 *str != '\0' 的判断,倒数第6行的 || 也写成了 &&。