zoukankan      html  css  js  c++  java
  • [leetcode]Wildcard Matching

    难题。一开始使用递归+备忘录的方式,我的递归写的太烂,大数据集合超时。要注意的是,一开始没考虑到"", "*"的case。超时的代码(即使后来加上长度的预先判断):

    class Solution {
    public:
        int matrix[1000][1000];
        bool isMatch(const char *s, const char *p) {
            int slen = strlen(s);
            int plen = strlen(p);
            const char* tmp = p;  
            int cnt = 0;  
            while (*tmp != '') if (*(tmp++) != '*') cnt++;  
            if (cnt > slen) return false;  
            memset(matrix, 0, sizeof(matrix));
            int r = isMatch(s, 0, slen, p, 0, plen);
            return (r == 1);
        }
         
    private:
        int isMatch(const char *s, int i, int slen, const char *p, int j, int plen)
        {
            if (matrix[i][j] != 0) return matrix[i][j];
            if (i == slen && j == plen) return 1;
            if (j == plen) return -1;
            if (i == slen && p[j] == '*')
            {
                matrix[i][j] = isMatch(s, i, slen, p, j+1, plen);
                return matrix[i][j];
            }
            if (p[j] == '?' || p[j] == s[i])
            {
                matrix[i][j] = isMatch(s, i+1, slen, p, j+1, plen);
                return matrix[i][j];
            }
            if (p[j] == '*')
            {
                bool r = isMatch(s, i+1, slen, p, j, plen) == 1
                    || isMatch(s, i, slen, p, j+1, plen) == 1;
                matrix[i][j] = r ? 1:-1;
                return matrix[i][j];
            }
            else
            {
                matrix[i][j] = -1;
                return matrix[i][j];
            }
        }
    };  

    参考里看到一个概念好的递归代码 http://discuss.leetcode.com/questions/222/wildcard-matching,虽然也大数据超时。精华部分是,如果遇到‘*’,那么s向右的任何一段子串和p跳过‘*’后的匹配成功都算成功:

    class Solution {
    public:
        bool isMatch(const char *s, const char *p) {
            if (*p == '*'){//return true;
                while(*p == '*') ++p;
                if (*p == '') return true;
                while(*s != '' && !isMatch(s,p)){
                    ++s;                
                }
                return *s != '';
            }
            else if (*p == '' || *s == '') return *p == *s;
            else if (*p == *s || *p == '?') return isMatch(++s,++p);
            else return false;
        }
    };
    

    但即使将上述方法转成备忘录模式,也超时。递归还是太多了。必须自底向上DP来做,总的来说,DP才是正道。这里有个很好的文章:http://www.iteye.com/topic/1131749 还有 http://blog.csdn.net/a83610312/article/details/9750655

    下面是DP的代码:

    class Solution {
    public:
        bool matrix[500][500];
        bool isMatch(const char *s, const char *p) {
            int slen = strlen(s);
            int plen = strlen(p);
             
            const char* tmp = p;  
            int cnt = 0;  
            while (*tmp != '') if (*(tmp++) != '*') cnt++;  
            if (cnt > slen) return false;  
    
            memset(matrix, 0, sizeof(matrix));
            matrix[0][0] = true; // i,j means length
            for (int i = 1; i <= plen; i++)
            {
                if (matrix[0][i-1] && p[i-1] == '*') matrix[0][i] = true;
                for (int j = 1; j <= slen; j++)
                {
                    if (p[i-1] == '*')
                    {
                        matrix[j][i] = (matrix[j-1][i] || matrix[j][i-1]);
                    }
                    else if (p[i-1] == '?' || p[i-1] == s[j-1])
                    {
                        matrix[j][i] = matrix[j-1][i-1];
                    }
                    else
                    {
                        matrix[j][i] = false;
                    }
                }
            }
            return matrix[slen][plen];
        }
    };

    其实DP是自然的,但是如果不用一开始的长度判断,依然会超时。

    其实长度判断也属于一种剪枝吧,用O(n)的复杂度判断对O(n^2)的DP剪枝,是很大的改善。

    由于F[i][j]只和上两个状态有关,所以可使用滚动数组省空间。

    网上也有用贪心的,可再研究。

    第二刷:

    关键在于,只要记录最后一个*就可以了,因为*可以匹配所有,如果*后面的没匹配上,就是*之后的问题,即使退回之前的*,情况只会更差。

    class Solution {
    public:
        bool isMatch(const char *s, const char *p) {
            int i = 0;
            int j = 0;
            int backup_i = -1;
            int backup_j = -1;
            while (s[i] != '') {
                if (s[i] == p[j] || p[j] == '?') {
                    i++; j++;
                } else if (p[j] == '*') {
                    backup_j = j;
                    backup_i = i;
                    j++;
                } else if (s[i] != p[j]) {
                    if (backup_j == -1) {
                        return false;
                    }
                    j = backup_j;
                    i = backup_i + 1;
                    backup_i = i;
                    j++;
                }
            }
            if (s[i] == '') {// && left all '*' return true;
                while (p[j] != '') {
                    if (p[j] != '*') {
                        return false;
                    }
                    j++;
                }
                return true;
            }
            return false;
        }
    };
    

      

  • 相关阅读:
    谷歌三架马车之 The Google File System 中文版
    数据集市 Data Mart
    VMware虚拟机ubuntu下安装VMware Tools步骤
    NOIP普及组 海港 题解
    HXD的DS
    离散化
    哈希表
    状态压缩DP 初探
    《信息学奥赛一本通》大盗阿福 题解
    NOIP 加工零件 题解
  • 原文地址:https://www.cnblogs.com/lautsie/p/3335789.html
Copyright © 2011-2022 走看看