[Leetcode] 44. Wildcard Matching 解题报告
来源:互联网 发布:网络电话卡违法吗 编辑:程序博客网 时间:2024/06/10 11:49
题目:
Implement wildcard pattern matching with support for '?'
and '*'
.
'?' Matches any single character.'*' Matches any sequence of characters (including the empty sequence).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") → falseisMatch("aa","aa") → trueisMatch("aaa","aa") → falseisMatch("aa", "*") → trueisMatch("aa", "a*") → trueisMatch("ab", "?*") → trueisMatch("aab", "c*a*b") → false
思路:
拿到这样的题目描述,不难想到动态规划。不过对于这道题目,动态规划的运行效率反而不是最优的,主要是因为没有利用到’*'的威力。具体看下面三种思路的分析及比较。
1、动态规划:定义dp[i][j]为一个布尔变量,代表s的前i个字符是否可以和p的前j个字符完全匹配成功。则递推方程如下:
1)如果p[j] == '*',则该‘*'即可以出现0次,也可以出现至少1次,即dp[i+1][j+1] = dp[i+1][j] || dp[i][j+1];
2)如果p[j] != '*',则完全可以匹配的条件是:s和t的当前最后一个字符可以匹配,s和t除去当前最后字符之外,其余前面的字符也可以完全匹配。
2、双线性扫描:考虑到‘*’可以匹配任意多个字符(也就是说,一旦出现‘*’,则此时所有s中已经扫描到的位置都可以被匹配),那么我们可以记录并不断更新每个‘*’至少需要匹配的字符长度。具体做法是:当出现一个‘*’时,则记录当前s字符串已经被扫描到的位置,再接着试图匹配s和t后面的字符位置。一旦发现后面位置无法匹配,则返回到这里,将不匹配的字符用当前最后一个‘*’来匹配(也就是说,‘*’至少需要匹配的字符长度一旦在后面无法匹配时会被迫递增)。最后再判断p的指针到最后都是‘*’,如果是,则可以匹配,否则就不可以匹配。(此解法参考了小榕流光的博客:http://blog.csdn.net/qq508618087/article/details/51044029)。
3、深度优先搜索:本质上该方法还是和双线性扫描的思路一致,只是用了深搜的实现方式。在遇到一个‘*’的时候,我们还是试图去寻找该‘*’至少需要匹配的字符串长度,以便于为后面尝试可能的匹配留下最大的搜索空间。此时将dfs的返回值定义为匹配的三种不同状态(见下面代码中的注释),以便于处理平凡情况以及有效剪枝。
实现发现,思路2和3的运行效率要远远高于思路1。
代码:
1、动态规划:
class Solution {public: bool isMatch(string s, string p) { int n1 = s.length(), n2 = p.length(); vector<vector<bool>> dp(n1+1, vector<bool>(n2+1, false)); dp[0][0] = true; for(int j = 0; j < n2; ++j) { if(p[j] == '*') dp[0][j+1] = dp[0][j]; } for(int i = 0; i < n1; ++i) { for(int j = 0; j < n2; ++j) { if(p[j] == '*') // dp[i+1][j] means p[j] matches 0 time // dp[i][j+1] means p[j] matches at least 1 time dp[i+1][j+1] = dp[i+1][j] || dp[i][j+1]; else // dp[i][j] means the whether the previous can be matched // (s[i] == p[j] || p[j] == '?') means whether the last charchater can be matched dp[i+1][j+1] = dp[i][j] && (s[i] == p[j] || p[j] == '?'); } } return dp[n1][n2]; }};2、双线性扫描:
class Solution {public: bool isMatch(string s, string p) { int preS = -1, preP = -1, i = 0, j = 0; int len1 = s.size(), len2 = p.size(); while(i < len1) { if(s[i] == p[j] || p[j] == '?') // matched i++, j++; else if(p[j] == '*') // at least we can match s[0, i] preS = i + 1, preP = j++; else if(preP == -1) // no previous matched case exists return false; else // re-match from here i = preS, j = preP; } while(p[j]=='*') // skip the more than necessary '*' j++; return i == len1 && j == len2; }};
3、深度优先搜索:
class Solution {public: bool isMatch(string s, string p) { return dfs(s, p, 0, 0) == 2; }private: int dfs(string& s, string& p, int si, int pi) { if (si == s.size() and pi == p.size()) return 2; // matched if (si == s.size() and p[pi] != '*') return 0; // unmatched: reached the end of s if (pi == p.size()) return 1; // unmatched: not reached the end of s if (p[pi] == '?' or s[si] == p[pi]) return dfs(s, p, si+1, pi+1); if (p[pi] == '*') { // calculate the shortest length p[pi] need to cover if (pi+1 < p.size() and p[pi+1] == '*') return dfs(s, p, si, pi+1); // skip duplicate '*' for(int i = 0; i <= s.size()-si; ++i) { int ret = dfs(s, p, si+i, pi+1); if (ret == 0 or ret == 2) // reached the end of s, so return immediately return ret; } } return 1; }};
- [leetcode] 44. Wildcard Matching 解题报告
- [Leetcode] 44. Wildcard Matching 解题报告
- Leetcode #44. Wildcard Matching 通配符匹配 解题报告
- LeetCode --- 44. Wildcard Matching
- [Leetcode] 44. Wildcard Matching
- Leetcode 44. Wildcard Matching
- leetcode 44. Wildcard Matching
- Leetcode 44. Wildcard Matching
- Leetcode:44. Wildcard Matching
- LeetCode 44. Wildcard Matching
- leetcode.44. Wildcard Matching
- LeetCode 44. Wildcard Matching
- Leetcode-44. Wildcard Matching
- [LeetCode] 44. Wildcard Matching
- [leetcode] 44. Wildcard Matching
- [LeetCode]--44. Wildcard Matching
- LeetCode 44. Wildcard Matching
- leetcode 44. Wildcard Matching
- 微软正式推出Windows Mobile 6
- 小白又来了。。。程序运行到登录界面,点击登录以后就报错停止运行了。
- 自定义listview的ArrayAdapter报空指针
- 如何读取手机上的通讯录和短信息?
- 寻找Windows Mobile开发高手
- [Leetcode] 44. Wildcard Matching 解题报告
- 求J2ME完整讲义
- 我在网易ASP专栏拷了份ASP源代码下来,不能运行,提示好像是每行都有错误,很不能理解!请大家帮我看看,谢谢!
- 输出循环问题
- j2me碰撞检测问题,请前辈指教
- 求解这个字符串的解析
- 这个是什么选项卡控件?
- 原有的记录的一个栏中添加问题
- 下拉框和输入框 求救!