关闭

[Leetcode] 44. Wildcard Matching 解题报告

标签: LeetcodeWildcard Matching解题报告Dynamic ProgrammingBacktracking
193人阅读 评论(0) 收藏 举报
分类:

题目

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") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("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;
    }
};

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

【LeetCode】Wildcard Matching 串匹配 动态规划

题目:Wildcard Matching /*LeetCode WildCard matching * 题目:给定一个目标串和一个匹配串,判定是否能够匹配 * 匹配串中的定义:字符————>字符...
  • u011955072
  • u011955072
  • 2015-03-28 23:24
  • 1550

Leetcode 解题报告

据说刷完leetcode是准备编程面试的第一步。想到明年可能就要开始找工作了,先准备着吧。 计划今年11月份前做完,大概平均每天2-3题,难度应该不大,贵在坚持! 代码放在github上,地址:htt...
  • Wiking__acm
  • Wiking__acm
  • 2016-06-20 15:58
  • 1087

Python学习(Leetcode 算法题解【1~20】)

掌握了python的基础概念,并不意味着就可以使用python来进行项目开发了。学习一门编程语言时,对于概念的掌握只是基础。用该语言去解决实际问题,并在解决问题的过程中学习才是学一门语言时费时较长的部...
  • Hans__Yang
  • Hans__Yang
  • 2016-07-20 21:35
  • 1381

Leetcode #44. Wildcard Matching 通配符匹配 解题报告

1 解题思想嗯,最近遇到要写Hard的频率偏高,而最近的重心也不再Leetcode上,心累。。Hard写起来都好麻烦。这道题好像之前也有几次,讲过类似的题目,也就是*能任意长度和字符匹配,?能匹配任意...
  • MebiuW
  • MebiuW
  • 2016-04-15 23:16
  • 1464

从代码的视角看DOS时代的通配符.pdf LeetCode 44. Wildcard Matching 正则

  • 2016-03-12 03:10
  • 435KB
  • 下载

[LeetCode] Regular Expression Matching 解题报告

[题目] mplement regular expression matching with support for ‘.’ and ‘*’. ‘.’ Matches any single ch...
  • hubin00sx
  • hubin00sx
  • 2017-02-20 19:36
  • 129

JAVA学习44_leetCode解题报告之Copy List with Random Pointer

题目: A linked list is given such that each node contains an additional random pointer which co...
  • wang_zhenwei
  • wang_zhenwei
  • 2017-02-21 14:48
  • 269

[Leetcode] 10. Regular Expression Matching 解题报告

题目: Implement regular expression matching with support for '.' and '*'. '.' Matches any single cha...
  • magicbean2
  • magicbean2
  • 2016-12-10 23:47
  • 276

Leetcode 44. Wildcard Matching

44. Wildcard Matching Total Accepted: 52808 Total Submissions: 307806 Difficulty: Hard Implem...
  • fantasiasango
  • fantasiasango
  • 2016-03-17 11:47
  • 208

LeetCode_44---Wildcard Matching

Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. ...
  • bingbing8219
  • bingbing8219
  • 2015-06-19 15:58
  • 245
    个人资料
    • 访问:89430次
    • 积分:6388
    • 等级:
    • 排名:第4439名
    • 原创:563篇
    • 转载:10篇
    • 译文:2篇
    • 评论:17条
    最新评论