这道题单论难度倒是不难,但是要考虑的方面比较多,因此很容易掉进坑里去。
题目的大意是模拟正则式匹配,合法的原串输入是26个小写字母,匹配正则串的输入是小写字母以及’.‘和’*’。
这其中唯一比较麻烦的就是*
了,因为它可以有0到原串长度的可能,所以我认为应该用递归来做(原来是用for循环,但是发现怎么都处理不好)
- 首先考虑到正常匹配情况,正常匹配的时候如果没有
*
,则一切正常;如果有*
,则需要去试探是否存在需要匹配多个字符的情况,因为可能会有这样的情况,对于aaa
,要求匹配aa*aa
这类的。 - 对于失配的情况下,如果存在
*
,则可以考虑0个的情况,跳过;不然直接返回false。 - 对于有字符串到达边界的情况,如果匹配正则串到达边界,则程序必定结束;如果原串到达边界,则还需要考虑到
*
的问题。比如对于空串来匹配c*c*
。
此外还需要注意一些细节,一个是内存访问可能超界的情况,我是用嵌套的if来判断的。还有一个是C中的if和else的配对问题,按照C语言中的定义,else总是和前面未配对的if配对,而不考虑作用域的问题。我没有验证C++里面是否存在这种现象,但还是尽量避免吧。
#include <string>
#include <iostream>
using namespace std;
class Solution {
public:
bool isMatch(string s, string p) {
return recursive(s,p,0,0);
}
bool recursive(string s,string p,int i,int j)
{
//cout<<i<<" "<<j<<endl;
if(i == s.length() && j == p.length())
{
return true;
}
else if(j>=p.length())
{
return false;
}
else if(i>=s.length())//consider *
{
if(j+1<p.length())
{
if(p[j+1]=='*'&&j+2<=p.length())
{
return recursive(s,p,i,j+2);
}
}
return false;
}
if(s[i]==p[j] || p[j]=='.')
{
if(j+1<p.length())//consider *
if(p[j+1]=='*')
{
bool flag = recursive(s,p,i,j+2);//consider 0 characters
if(flag)
{
return flag;
}
for(unsigned int k = 0;(s[i+k] == p[j] || p[j]=='.')&&i+k<s.length();k++)
{
flag = recursive(s,p,i+k+1,j+2);
if(flag)
{
return true;
}
}
return false;
}
return recursive(s,p,i+1,j+1);
}
else if(s[i]!=p[j] && p[j]!='.')//consider *
{
if(j+1<p.length()&&p[j+1]=='*')
{
bool flag = recursive(s,p,i,j+2);//consider 0 characters
if(flag)
{
return flag;
}
}
return false;
}
}
};
int main(void)
{
Solution s;
string a = "";
string b = "c*";
cout<<s.isMatch(a,b)<<endl;
return 0;
}