class Solution { #define SINGLE 1 #define MULTIP 2 public: bool isMatch(const char *s, const char *p) { if (s == NULL || p == NULL) return true; vector<pair<char, int> > pattern; int pos = 0; char ch = '\0'; while ((ch = p[pos++]) != '\0') { if (ch == '*') { pattern.back().second = MULTIP; continue; } pattern.push_back(make_pair(ch, SINGLE)); } return isMatch(s, 0, pattern, 0); } bool isMatch(const char *s, int pos, vector<pair<char, int> > &pattern, int ppos) { if (ppos == pattern.size()) { return s[pos] == '\0'; } int i = pos; pair<char, int> &p = pattern[ppos]; int offset = (p.second == SINGLE) ? 0 : -1; char ch = '\0'; while (offset < 0 || (ch = s[pos + offset]) != '\0') { if (offset >= 0 && !cmp(ch, p.first)) { return false; } if (isMatch(s, pos + offset + 1, pattern, ppos + 1)) { return true; } if (p.second == SINGLE) break; offset++; } return false; } bool cmp(const char a, const char b) { if (a == '.' || b == '.') return true; return a == b; } };
暴力法, 216ms,
改写为记忆搜索,这里假设字符串和模式字符串的长度都不超过unsigned short 范围(6w+), 84ms
class Solution { #define SINGLE 1 #define MULTIP 2 private: unordered_map<unsigned int, bool> memo; public: bool isMatch(const char *s, const char *p) { if (s == NULL || p == NULL) return true; memo.clear(); vector<pair<char, int> > pattern; int pos = 0; char ch = '\0'; while ((ch = p[pos++]) != '\0') { if (ch == '*') { pattern.back().second = MULTIP; continue; } pattern.push_back(make_pair(ch, SINGLE)); } return isMatch(s, 0, pattern, 0); } bool isMatch(const char *s, int pos, vector<pair<char, int> > &pattern, int ppos) { unsigned int id = (pos << 16) | ppos; unordered_map<unsigned int, bool>::iterator iter = memo.find(id); if (memo.find(id) != memo.end()) return iter->second; bool res = false; if (ppos == pattern.size()) { res = s[pos] == '\0'; memo.insert(make_pair(id, res)); return res; } int i = pos; pair<char, int> &p = pattern[ppos]; int offset = (p.second == SINGLE) ? 0 : -1; char ch = '\0'; while (offset < 0 || (ch = s[pos + offset]) != '\0') { if (offset >= 0 && !cmp(ch, p.first)) { res = false; break; } if (isMatch(s, pos + offset + 1, pattern, ppos + 1)) { res = true; break; } if (p.second == SINGLE) break; offset++; } memo.insert(make_pair(id, res)); return res; } bool cmp(const char a, const char b) { if (a == '.' || b == '.') return true; return a == b; } };
第二轮:
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
看到这样的题真有点写不下去,还是找了一发资料:
class Solution { public: bool isMatch(const char *s, const char *p) { if (s == NULL || p == NULL) { return false; } if (*p == '\0') { return *s == '\0'; } if (*(p+1) != '*') { return (*p == *s || (*p == '.' && *s != '\0')) && isMatch(s + 1, p + 1); } char curpat = *p; const char* sp = s; while (*sp == curpat || (curpat == '.' && *sp != '\0')) { if (isMatch(sp, p + 2)) { return true; } sp++; } return isMatch(sp, p + 2); } };
在discuss里找到一个dp解法:
class Solution { public: bool isMatch(const char *s, const char *p) { const int slen = strlen(s); const int plen = strlen(p); vector<vector<bool> > dp(slen+1, vector<bool>(plen+1, false)); // when src string is empty, pattern string should be in form of // a*b*c*... for (int i=2; i<=plen; i+=2) { if (p[i-1] == '*') { dp[0][i] = true; } else { break; } } dp[0][0] = true; for (int i=1; i<=slen; i++) { for (int j=1; j<=plen; j++) { if (s[i-1] == p[j-1] || p[j-1] == '.') { dp[i][j] = dp[i-1][j-1]; continue; } if (p[j-1] == '*') { if (p[j-2] == s[i-1] || p[j-2] == '.') { dp[i][j] = dp[i-1][j] || dp[i][j-2]; } else { dp[i][j] = dp[i][j-2]; } } } } return dp[slen][plen]; } };