问题:给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。(leetcode10 hard)
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
输入:两个字符串变量s和p
输出:是否匹配
思路:
主要需要注意模式串中的*,如果为*,则模式串的指针有可能不动,也有可能跳动两个位置。
代码:
class Solution {
public:
bool matchCore(char* s,char* p)
{
if(*s=='\0'&&*p=='\0')
return true;
if(*s!='\0'&&*p=='\0')
return false;
if(*(p+1)=='*')
{
if(*p==*s||(*p=='.'&&*s!='\0'))
return matchCore(s+1,p+2)|| //matchCore(s+1,p+2) 可由matchCore(s+1,p)和matchCore(s,p+2)替代
matchCore(s+1,p)||
matchCore(s,p+2);
else
return matchCore(s,p+2);
}
if(*p==*s||(*p=='.'&&*s!='\0'))
return matchCore(s+1,p+1);
return false;
}
bool isMatch(string s, string p) {
if(s!=""&&p=="")
return false;
if(s==""&&p=="")
return true;
return matchCore(&s[0], &p[0]);
}
};
复杂度分析:时间复杂度为,空间复杂度为O(p).
扩展:时间复杂度太高了。模式能匹配的时候,必有模式的子模式匹配字符串的子串。因此可以使用动态规划算法。时间复杂度为O(SP).
定义d[i][j]为s从i开始到结尾,p从j开始到结尾是否能够匹配。
最优子结构:
- 如果 p[j+1] 不是通配符 * ,则 f[i][j] 是真,当且仅当 s[i] 可以和 p[j] 匹配,且 f[i+1][j+1] 是真。
- 如果 p[j+1] 是通配符 * ,则下面的情况只要有一种满足,f[i][j] 就是真:
f[i][j+2] 是真
s[i] 可以和 p[j] 匹配,且 f[i+1][j] 是真。(比如 s 串是 aaaaa , p 串是 a*a)