题目:
请实现一个函数用来匹配包含’ . '和 ’ * ‘的正则表达式。模式中的字符 ’ . ’ 表示任意一个字符,而’ * ’ 表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。
例如,字符串" aaa ”与模式"a . a”和"ab * a c * a”匹配,但与“aa.a”和"ab*a均不匹配。
分析:本题说到底就是通过对模式字符串进行一些替换或者省略其中一些字符,让它与要匹配的字符串变得完全一致。
我们每次都取一个字符,如果字符串的第一个字符与模式串的第一个字符相同,那么二者都向下走,如果不同,就直接返回false。
这里由于 . 可以替代任意一个字符, 所以二者相等的判断,除了 正常的 * str== * pattern ;
还有 *pattern == ' . ' &&*str != ' \0 ' ;
如果到了最后一位 . 替代了str的 ‘\0’ 那么str再移动就会越界 所以*str != ‘\0’ 。
如果模式中第一个字符与字符串中的第一个字符相等,且模式中第二个字符为 * 时问题要复杂一些 ,它的定义是它前面的字符可以出现0次或1次或多次。对前面的字符造成影响,所以我们要先判断分析第二个字符为 * 的情况。
1)出现0次就是省略了这个字符 ,原字符串不动,模式字符串后移两位 。
2)出现一次就是还是原来的一个字符,原字符串后移1位 ,模式字符串后移2位。
3)出现多次,比如 aaa 和 a * , a* 代表可以代表a出现了很多次 ,原字符串向后移动 ,模式字符串不动 。(匹配aaa的第一个a时 相当于 a * 变成了 aa * , 匹配aaa的第二个a时,相当于 a* 变成了 aaa*,匹配aaa的第三个a时,相当于aaa * 变成了 aaaa* ,最后变成 ’ \0 ’ 和 a* ,匹配字符串的第二个字符为 * 可以选择忽略前面这个字符,向后移动两个,也变成了 ’ \0 ',两者相等,返回 true 。)
如果模式中第二个字符为 * 但是第一个字符二者不等 那么 模式直接跳过这个字符
综上情况总结:
模式第二个字符 为 * : 第一个字符相等,分为三种情况向下移动 ;第一个字符不相等直接跳过 。
模式第二个字符不为 * : 二者相等,向下走;不相等直接false。
#include<iostream>
using namespace std;
bool matchCore(char *str , char *pattern);
bool match(char *str , char *pattern){
if(str == NULL || pattern == NULL)
return false;
return matchCore(str,pattern);
}
bool matchCore(char *str ,char *pattern)
{
if(*str == '\0' && * pattern == '\0')
return true;
if(*str != '\0' && *pattern == '\0') //模式字符串经过变换最后应该会和匹配串相同 所以如果模式串先到了结尾 而匹配串还没匹配完 那一定不等
//但是匹配串却可以先到结尾 如上面的aaa和a*的例子
return false;
if(*(pattern+1) == '*')
{
if(*pattern == *str ||(*pattern == '.'&&*str != '\0'))
return matchCore(str,pattern+2)|| //0次
matchCore(str+1,pattern+2) || //1次
matchCore(str+1,pattern); //多次
else
return matchCore(str,pattern+2);
}
if(*str == *pattern || (*pattern =='.'&&*str != '\0'))
return matchCore(str+1,pattern+1);
return false;
}
int main()
{
char *str = "aaa";
char *pattern1 = "a*";
char *pattern2 = "aa.a";
char *pattern3 = "b*a*aab*a";
char *pattern4 = "";
cout<<match(str,pattern1)<<endl;
cout<<match(str,pattern2)<<endl;
cout<<match(str,pattern3)<<endl;
cout<<match(str,pattern4)<<endl;
return 0;
}