Regular Expression Matching
2017-03-23 19:23
176 查看
一. Regular Expression Matching
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
Difficulty:Hard
TIME:TIMEOUT
解法一(深度优先搜索)
这道题主要是要理解匹配的过程,就是要把匹配的过程分成几种情况分别讨论,最简单的做法当然是用递归来求解,以下就对递归过程做一个描述。
首先是有*号的情况,也就是匹配0次或者1次以上:
如果匹配0次,则isMatch(s,p) = isMatch(s,p.substr(2))
如果匹配一次以上,则isMatch(s,p) = isMatch(s.substr(1),p)
然后是没有*号的情况,也就是只匹配一次:
则isMatch(s,p) = isMatch(s.substr(1),p.substr(1))
void dfs(string s, int ss, string p, int pp, bool &result) { if (pp >= p.size() && ss >= s.size()) result = true; if (result || pp >= p.size()) return; if (pp + 1 < p.size() && p[pp + 1] == '*') { //有*的情况 dfs(s, ss, p, pp + 2, result); //必定可以跳过 if ((p[pp] == '.' || p[pp] == s[ss]) && ss + 1 <= s.size()) dfs(s, ss + 1, p, pp, result); //但不一定能匹配一次以上 } else if ((p[pp] == '.' || p[pp] == s[ss]) && ss + 1 <= s.size()) dfs(s, ss + 1, p, pp + 1, result); //没有*的情况 } bool isMatch(string s, string p) { bool result = false; dfs(s, 0, p, 0, result); return result; }
代码的时间复杂度应该约为O(2n)。
解法二(动态规划)
一开始压根没有想到这道题能用动态规划来解,但确实可以这样,因为这道确实存在着最优子结构,而且和之前做过的Distinct Subsequences十分相似。
首先使用一个二维数组dp,第一维表示字符串s的长度,而第二维表示字符串p的长度(注意是长度而不是下标),值为true或false,也就是p的前缀能否匹配s的前缀。
为什么要采用长度而不是下标呢,首先一点处理空串会简单很多(如果采用下标,空串要单独处理),第二点是可以避免很多的边界条件判断(之前要处理下标是-1的状态,现在只需要处理下标是0的状态就行了)。因此代码会简洁不是一点,Distinct Subsequences的处理方式也是同样的道理 。
首先处理空串的情况,很容易理解dp[0][0]为true,然后就是dp[0][j]的情况,也容易想到可以一直匹配成功直到出现第一个没有带*号的字符。而具体的最优子结构我直接用LeetCode上面的其他人写的作为参照,将会在代码中给出:
/** * f[i][j]: if s[0..i-1] matches p[0..j-1] * if p[j - 1] != '*' * f[i][j] = f[i - 1][j - 1] && s[i - 1] == p[j - 1] * if p[j - 1] == '*', denote p[j - 2] with x * f[i][j] is true iff any of the following is true * 1) "x*" repeats 0 time and matches empty: f[i][j - 2] * 2) "x*" repeats >= 1 times and matches "x*x": s[i - 1] == x && f[i - 1][j] * '.' matches any single character */ bool isMatch(string s, string p) { vector<vector<bool>> dp(s.size() + 1, vector<bool>(p.size() + 1, false)); dp[0][0] = true; for (int i = 1; i <= p.size(); i++) { //先处理空串的情况 if (p[i - 1] == '*' && dp[0][i - 2]) dp[0][i] = true; } for (int i = 1; i <= s.size(); i++) { for (int j = 1; j <= p.size(); j++) { if (j < p.size() && p[j] == '*') { if(dp[i][j - 1] || ((s[i - 1] == p[j - 1] || p[j - 1] == '.') && dp[i - 1][j + 1])) dp[i][j + 1] = true; } else if (dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.')) { dp[i][j] = true; } } } return dp[s.size()][p.size()]; }
不得不说这个最优子结构是十分精妙的,很少的判断,很少的步骤,就能涵盖所有的情况。
代码的时间复杂度为O(n2)。
相关文章推荐
- leetcode(10) - Regular Expression Matching 正则表达式匹配
- Regular Expression Matching
- 【LeetCode with Python】 Regular Expression Matching
- LeetCode 10. Regular Expression Matching
- leetcode---regular-expression-matching---字符串
- LeetCode: Regular Expression Matching
- leetcode 10. Regular Expression Matching
- leetcode Regular Expression Matching
- [LeetCode]Regular Expression Matching、Wildcard Matching
- Regular Expression Matching
- Regular Expression Matching
- [leetcode 10] Regular Expression Matching
- 【leetcode刷题笔记】Regular Expression Matching
- Regular Expression Matching
- Regular Expression Matching in the Wild
- Regular Expression Matching
- 【leetcode】Regular Expression Matching (hard) ★
- Leetcode -- Regular Expression Matching
- 【leetcode】Regular Expression Matching
- regular expression matching