链接:http://leetcode.com/onlinejudge#question_10
原题:
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
思路:这道题目和Wildcard Matching基本一样,只是测试用例弱很多。
两种方法,DFS和DP。
就讲讲DP吧。
不知道是否有不合法的正则串,不过我都检查了。
状态转移方程:state[strlen(s)+1][strlen(p)+1]
对于s[i], p[j]
1. if p[j] == '.', then state[i+1][j+1] = state[i][j]
2. if p[j] == '*', then
1) if p[j-1] == '.', then state[i+1][j+1] = hasTrue[j-1] (j-1列有true)
2) if p[j-1] == '*', then return false;
3) else, 检查s的最后一段是不是都是一样的元素
3. else
1) if s[i] == p[j], then state[i+1][j+1] = state[i][j], else false
代码:
DP
class Solution {
public:
bool isMatch(const char *s, const char *p) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int sLen = strlen(s);
int pLen = strlen(p);
if (pLen > 0 && *p == '*')
return false;
vector<bool> hasTrue(pLen+1);
vector<vector<bool> > state(sLen+1, hasTrue);
state[0][0] = hasTrue[0] = true;
for (int n=1; n<pLen; n+=2) {
if (p[n] == '*') {
state[0][n+1] = true;
hasTrue[n+1] = true;
} else {
break;
}
}
for (int i=0; i<sLen; i++) {
for (int j=0; j<pLen; j++) {
if (p[j] == '.') {
state[i+1][j+1] = state[i][j];
} else if (p[j] == '*') {
if (p[j-1] == '*')
return false;
else if (p[j-1] == '.')
state[i+1][j+1] = hasTrue[j-1];
else {
state[i+1][j+1] = state[i+1][j-1];
int n = i;
while (n>=0 && s[n] == p[j-1] && !state[i+1][j+1]) {
if (state[n][j-1]) {
state[i+1][j+1] = true;
break;
}
n--;
}
}
} else {
if (s[i] == p[j])
state[i+1][j+1] = state[i][j];
else
state[i+1][j+1] = false;
}
if (state[i+1][j+1])
hasTrue[j+1] = true;
}
}
return state[sLen][pLen];
}
};
DFS
class Solution {
public:
bool isMatch(const char *s, const char *p) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if (s == NULL || p == NULL) {
if (s == NULL && p == NULL)
return true;
else
return false;
}
if (*s == '\0' && *p == '\0')
return true;
if (*p == '\0')
return false;
if (*(p+1) == '*') {
int i;
for (i=0; *(s+i) != '\0'; i++) {
if (i>0 && *p != '.' && *p != *(s+i-1))
break;
if (isMatch(s+i, p+2))
return true;
}
if (*(s+i) == '\0') {
if (i > 0 && *p != '.' && *p != *(s+i-1))
return false;
return isMatch(s+i, p+2);
}
return false;
} else {
if (*s && (*s == *p || *p == '.'))
return isMatch(s+1, p+1);
return false;
}
}
};