题目:https://leetcode.com/problems/regular-expression-matching/#/description
Implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
The function prototype should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
分析
:
刚开始想直接匹配,但对于带*的,就很难做判断。想了很久才想通dp来做比较简单
f[i][j]: s[0..i-1] 是否匹配p[0..j-1]
if p[j - 1] != '*'
f[i][j] = f[i-1][j-1]&& (p[j-1]=='.'||s[i-1]==p[j-1])
if p[j - 1] == '*', 设 p[j - 2] 为 x
1) "x*" 重复0次:f[i][j] = f[i][j - 2]
2)"x*" 重复1次以上:f[i][j] = f[i-1][j] && (p[j-2]=='.'||s[i-1]==p[j-2])
注意这里只需要转移重复一次的情况,而不需要枚举重复的次数。还有初始化需要分类,这个想一下也很容易想通。
c++实现:bool isMatch(string s, string p)
{
int m=s.length(), n=p.length();
bool f[m+1][n+1];
f[0][0] = 1;
for(int i=1; i<=m; ++i)
f[i][0] = 0;
for(int i=1; i<=n; ++i)
if(p[i-1]!='*')
f[0][i] = 0;
else
f[0][i] = f[0][i-2];
for(int i=1; i<=m; ++i)
for(int j=1; j<=n; ++j)
{
if(p[j-1]!='*')
f[i][j] = f[i-1][j-1]&& (p[j-1]=='.'||s[i-1]==p[j-1]);
else
f[i][j] = f[i][j-2] || (f[i-1][j]&& (p[j-2]=='.'||s[i-1]==p[j-2]));
}
return f[m][n];
}