题目描述
请实现一个函数用来匹配包括’.‘和’*‘的正则表达式。模式中的字符’.'表示任意一个字符,而星号表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配
思路
1、首先考虑字符串与模式串中有空串的情况:
a.当字符串和模式串都为空的时候,说明匹配完成,返回true。
b.当字符串不为空,模式串为空时,说明匹配失败,返回false。
2、当字符串为空,模式串不为空时,有匹配成功的可能,如a*a*。还有字符串和模式串都不为空时,需进一步讨论。因为星号的特殊性,所以我们以模式串当前位的下一位是否是星号分为两种情况:
a.模式串的下一位不是星号:判断字符串与模式串当前位是否相同,如果相同或者模式串当前位是‘.’且字符串当前位不是‘\0’时,则当前位匹配成功,字符串与模式串接着比较下一位;否则直接返回false。
b.模式串的下一位是星号:判断字符串与模式串当前位是否相同,如果相同或者模式串当前位是‘.’且字符串当前位不是‘\0’时,模式串该位可以选择匹配0次(模式串移动2位,字符串不动)或者选择匹配1次(模式串不动,字符串移动1位);如果字符串与模式串当前位不相同,模式串该位只能匹配0次,即模式串移动2位,字符串不动。
代码(c++)
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(*str==*pattern||(*pattern=='.'&&*str!='\0')){//'.'可以匹配除了'\0'之外的所有字符
return match(str+1,pattern+1);
}
else return false;
}
else{
if(*str==*pattern||(*pattern=='.'&&*str!='\0')){
return match(str+1,pattern)||match(str,pattern+2);
}
else return match(str,pattern+2);
}
}
};
LeetCode 10.正则表达式匹配
这道题与上面的题是一样的,不同的是,如果用同样的代码,LeetCode某些测试用例会超时。因为上面的代码在递归时会重复查找。于是用动态规划的思路,用一个二维数组dp[i][j]存放已经判断过的以s[i],p[j]为首字母的匹配串和模式串是否匹配。过程如下
创建一个flag[s.length()+1][p.length()+1]大小的表格,用来记录以s[i],p[j]为首字母的匹配串和模式串是否匹配。从表格尾开始逐层像flag[0][0]移动。初始化所有元素为false。
1.一开始flag[s.length()][p.length()]=true,因为两个都为空时视为匹配。
2.对于其他元素,如果当前元素后一个元素不是*,就看此时模式串与匹配串对应字符是否匹配,以及其后的元素是否已经匹配flag[i+1][j+1];否则,当前模式串元素匹配0个flag[i][j+2]或1个flag[i+1][j])匹配串字符(此时模式串与匹配串对应字符匹配)。
~~~~
3.对于最后一列元素(除了flag[s.length()][p.length()]),意味着模式串为空匹配串不为空,此时匹配失败,所以都是false。
4.最终flag[0][0]即为结果。
代码(c++)
class Solution {
public:
bool isMatch(string s, string p) {
bool** flag=new bool*[s.length()+1];
for(int i=0;i<s.length()+1;i++){
flag[i]=new bool[p.length()+1];
for(int j=0;j<p.length();j++){
flag[i][j]=false;
}
}
flag[s.length()][p.length()]=true;
for(int i=s.length();i>=0;i--){
for(int j=p.length();j>=0;j--){
if(i==s.length()&&j==p.length()) continue;
else if(j==p.length()){
flag[i][j]=false;
continue;
}
bool firstelem=i<s.length()&&(s[i]==p[j]||p[j]=='.');
if(p[j+1]!='*'){
flag[i][j]=firstelem&&flag[i+1][j+1];
}
else{
flag[i][j]=(firstelem&&flag[i+1][j])||flag[i][j+2];
}
}
}
return flag[0][0];
}
};