问题描述:
请实现一个函数用来匹配包括 ‘.’ 和 ‘*’ 的正则表达式。模式中的字符 ‘.’ 表示任意一个字符,而 ‘*’ 表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
解决思路:
解决该问题的关键在于将匹配的情况考虑全面。加入 ‘*’ 这个符号将导致问题变得复杂,所以分情况讨论 ‘*’ 带来的影响。首先, ‘*’ 作用于某一个字符的后一位,这决定了我们在分析匹配情况时每次考虑模式串里的相邻两个字符。
-
假如,第二个字符不是 ‘*’ ,则比较第一个字符和当前的字符串的字符是否相同即可(这里相等的情况还包括模式串的当前第一个字符是 ‘.’)。若相同,则字符串与模式串都后移一位,然后比较后面的子串是否匹配;若不同,直接说明二者不匹配。
-
假如,第二个字符是 ‘*’ ,再分两种情况讨论:
-
模式串当前两个字符中第一个字符与字符串当前字符不相同,则将模式串当前字符后移两位,字符串当前字符位置不变,再比较是否匹配。例:b 与 a* b 匹配,实际上a*的数目是0,这种情况。
-
模式串当前两个字符中第一个字符与字符串当前字符相同,则会有三种情况:
- 将模式串后移两位,字符串当前位置不变,然后比较后面子串是否匹配。例:b 与 a* b 匹配,实际上a*的数目是0,这种情况。
- 将模式串后移两位,字符串当前位置后移一位,然后比较后面子串是否匹配。例:ab 与 a* b 匹配,实际上a的数目是1,这种情况。
- 模式串当前位置不变,字符串当前位置后移一位,然后比较后面子串是否匹配。例:aa 与 a* b 匹配,实际上a的数目大于1,这种情况。
-
C++代码:
分情况递归即可解决上述问题。
class Solution {
public:
bool match(char* str, char* pattern)
{
if(str == NULL || pattern == NULL)
return false;
return matchCore(str, 0, pattern, 0);
}
bool matchCore(char* str, int strIndex, char* pattern, int patternIndex)
{
// 字符串与模式串同时读取完毕,则匹配完成,匹配成功
if(strIndex == strlen(str) && patternIndex == strlen(pattern))
return true;
// 字符串未读取完毕,模式串已被读取完毕,则匹配失败
if(strIndex != strlen(str) && patternIndex == strlen(pattern))
return false;
// 模式串当前不能选取两个字符,则仅比较当前字符即可
if(patternIndex + 1 == strlen(pattern))
{
if(strIndex != strlen(str) && (str[strIndex] == pattern[patternIndex] || pattern[patternIndex] == '.'))
return matchCore(str, strIndex + 1, pattern, patternIndex + 1);
else
return false;
}
// 模式串当前能选取两个字符
else
{
// 模式串当前第二个字符为'*'
if(pattern[patternIndex+1] == '*')
{
// 模式串当前第一个字符与字符串相同
if(strIndex != strlen(str) && (str[strIndex] == pattern[patternIndex] || pattern[patternIndex] == '.'))
{
// 思路分析阐述的三种情况,哪一种成功匹配都说明二者可以匹配,用或连接
return (matchCore(str, strIndex, pattern, patternIndex + 2) ||
matchCore(str, strIndex + 1, pattern, patternIndex + 2) ||
matchCore(str, strIndex + 1, pattern, patternIndex));
}
// 模式串当前第一个字符与字符串不同
else
{
return matchCore(str, strIndex, pattern, patternIndex + 2);
}
}
// 模式串当前第二个字符不为'*'
else
{
if(str[strIndex] == pattern[patternIndex] || pattern[patternIndex] == '.')
return matchCore(str, strIndex + 1, pattern, patternIndex + 1);
else
return false;
}
}
}
};