LeetCode 10 - Regular Expression Matching
2015-12-21 16:22
429 查看
Regular Expression Matching
Implement regular expression matching with support for
Runtime: 20 ms
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 Code
class Solution { public: /* dp[i][j]: * true -> s[0...i-1] matches p[0...j-1] * flase -> otherwise * * (1) trivial string * p[i][j] = p[i-1][j-1], if p[j-1] != '*' && (s[i-1] == p[j-1] || p[j-1] == '.') * (2) x* matches empty string * p[i][j] = p[i][j-2], if p[j-1] == '*' * (3) x* -> xx*, i.e. x repeats for at least 1 times * p[i][j] = p[i-1][j] && (s[i-1] == p[j-2] || p[j-2] == '.'), if p[j-1] == '*' */ bool isMatch(string s, string p) { int m = s.length(), n = p.length(); vector<vector<bool> > dp(m+1, vector<bool>(n+1, false)); dp[0][0] = true; // initialization for (int i = 0; i <= m; i++) for (int j = 1; j <= n; j++) if (p[j-1] == '*') dp[i][j] = dp[i][j-2] || i > 0 && dp[i-1][j] && (s[i-1] == p[j-2] || p[j-2] == '.'); else dp[i][j] = i > 0 && dp[i-1][j-1] && (s[i-1] == p[j-1] || p[j-1] == '.'); return dp[m] ; } };
Runtime: 20 ms
Backtrack Code
struct backtrackPoint { int stringIndex, patternIndex; backtrackPoint() { stringIndex = patternIndex = 0; } backtrackPoint(int stringIndex, int patternIndex): stringIndex(stringIndex), patternIndex(patternIndex){ } }; struct pattern { string s; pattern(const string& s): s(s) { c = '\0'; } char c; pattern(char c): c(c) { s = ""; } pattern() { c = '\0'; s = ""; } }; class Solution { public: bool isMatch(string s, string p) { // get patterns vector<pattern> patterns; int start = 0, end = 0; for (int i = 0; i < p.length(); i++) { if (p[i] == '.') { end = i - 1; if (end >= start) patterns.push_back(pattern(p.substr(start, end - start + 1))); if (i+1 < p.length() && p[i+1] == '*') { patterns.push_back(pattern('.')); i++; } else patterns.push_back(pattern(".")); start = i + 1; } else if (p[i] == '*') { end = i - 2; if (end >= start) patterns.push_back(pattern(p.substr(start, end - start + 1))); patterns.push_back(pattern(p[i-1])); start = i + 1; } } if (p[p.length() - 1] != '*') patterns.push_back(pattern(p.substr(start))); // print patterns /* for (int i = 0; i < patterns.size(); i++) { cout << "Patterns[" << i << "]: "; if (patterns[i].s.length() > 0) cout << patterns[i].s << " "; else cout << patterns[i].c << "* "; cout << endl; } */ int patternIndex = 0; int m = 0; stack<backtrackPoint> backtrackPoints; bool backtrack = false; while (true) { //cout << "stringIndex: " << m << " patternIndex: " << patternIndex << " backtrackPoints.size(): " << backtrackPoints.size() << endl; if (patternIndex == patterns.size()) // pass all sub pattern(s), check { if (m == s.length()) return true; if (m < s.length()) // the whole string matches preceding sub pattern(s) of the whole pattern, backtrack { if (backtrackPoints.size() > 0) { backtrackPoint point = backtrackPoints.top(); backtrackPoints.pop(); m = point.stringIndex; patternIndex = point.patternIndex; backtrack = true; continue; } else return false; } } pattern currentPattern = patterns[patternIndex]; if (m == s.length()) { bool flag = true; for (int idx = patternIndex; idx < patterns.size(); idx++) if (patterns[idx].s.length() > 0) { flag = false; break; } if (flag) // current and latter sub pattern(s) are all star expression(s) return true; else // backtrack { if (backtrackPoints.size() > 0) { backtrackPoint point = backtrackPoints.top(); backtrackPoints.pop(); m = point.stringIndex; patternIndex = point.patternIndex; backtrack = true; continue; } else return false; } } if (currentPattern.s.length() > 0) // trivial string { if (currentPattern.s.compare(".") == 0 || s.compare(m, currentPattern.s.length(), currentPattern.s) == 0) { m += currentPattern.s.length(); patternIndex++; } else // backtrack { if (backtrackPoints.size() > 0) { backtrackPoint point = backtrackPoints.top(); backtrackPoints.pop(); m = point.stringIndex; patternIndex = point.patternIndex; backtrack = true; continue; } else return false; } } else // star expression { if (backtrack == true) // eat a character { backtrack = false; if (currentPattern.c == '.' || s[m] == currentPattern.c) // eat a character { m++; backtrackPoints.push(backtrackPoint(m, patternIndex)); patternIndex++; } else // backtrack { if (backtrackPoints.size() > 0) { backtrackPoint point = backtrackPoints.top(); backtrackPoints.pop(); m = point.stringIndex; patternIndex = point.patternIndex; backtrack = true; continue; } else return false; } } else // eat no character, i.e. pass current star expression { backtrackPoints.push(backtrackPoint(m, patternIndex)); patternIndex++; } } } cout << "Error: undefined!" << endl; } };Runtime: 368 ms
Recursive Code
class Solution { public: bool isMatch(string s, string p) { if (p.empty()) return s.empty(); if (p[1] == '*') // x* matches empty string or at least one character: x* -> xx* return isMatch(s, p.substr(2)) || !s.empty() && (s[0] == p[0] || '.' == p[0]) && isMatch(s.substr(1), p); else // trivial string return !s.empty() && (s[0] == p[0] || '.' == p[0]) && isMatch(s.substr(1), p.substr(1)); } };Runtime: 624 ms
相关文章推荐
- [leetcode] 37. Sudoku Solver 解题报告
- Android应用实现微信登录与分享
- 好用的文本编缉主题
- iOS: TableView如何刷新指定的cell 或section
- 读书笔记 --《数学之美》_信息的度量和作用
- 应用信息PackageManager
- iOS 7 present/dismiss自定义转场动画
- [Cryptography] Hash Password, Nonce
- 分页处理 jquery ajax
- 《失业的程序员》读后感
- 提取字符串中的数字-非指针版-(C语言描述)
- GitHub
- 数据库设计学习记录
- 信号和槽
- xargs 和 exec
- echarts学习总结(一):jsp整体框架
- Java中管理资源的引用队列相关原理解析
- rk3288_4.4SDK光感patch—CM3218
- Eclipse远程调试
- 多线程代码编写