[LeetCode] Wildcard Matching 通配符匹配

 

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

这道题通配符匹配问题还是小有难度的,这道里用了贪婪算法Greedy Alogrithm来解,由于有特殊字符*和?,其中?能代替任何字符,*能代替任何字符串,那么我们需要定义几个额外的指针,其中scur和pcur分别指向当前遍历到的字符,再定义pstar指向p中最后一个*的位置,sstar指向此时对应的s的位置,具体算法如下:

- 定义scur, pcur, sstar, pstar

- 如果*scur存在

  - 如果*scur等于*pcur或者*pcur为 '?',则scur和pcur都自增1

  - 如果*pcur为'*',则pstar指向pcur位置,pcur自增1,且sstar指向scur

  - 如果pstar存在,则pcur指向pstar的下一个位置,scur指向sstar自增1后的位置

- 如果pcur为'*',则pcur自增1

- 若*pcur存在,返回False,若不存在,返回True

 

class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        const char *scur = s, *pcur = p, *sstar = NULL, *pstar = NULL;
        while (*scur) {
            if (*scur == *pcur || *pcur == '?') {
                ++scur;
                ++pcur;
            } else if (*pcur == '*') {
                pstar = pcur++;
                sstar = scur;
            } else if (pstar) {
                pcur = pstar + 1;
                scur = ++sstar;
            } else return false;
        } 
        while (*pcur == '*') ++pcur;
        return !*pcur;
    }
};

 

这道题考虑看能不能用动态规划Dynamic Programming来解,开始写了个二维dp,发现说内存超了,于是改成了一维dp,发现最后一个test case过不去,一看那个case,字符串长达三万多个,OJ还是一如既往的丧心病狂,看到网上有人用if条件强行跳过这个case (参见这里),但是我感觉既然OJ这么卡内存和时间,估计就是不想我们用DP来解,还是好好掌握上面那种方法比较好,最后还是把DP也贴出来吧,虽然没法通过最后一个test case:

 

// Cannot pass the last test case
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        int m = strlen(s), n = strlen(p);
        vector<bool> dp(m + 1, false);
        dp[0] = true;
        for (int j = 0; j < n; ++j) {
            if (p[j] != '*') {
                for (int i = 0; i < m; ++i) {
                    dp[i + 1] = dp[i] && (p[j] == s[i] || p[j] == '?');
                }
            } else {
                int i = 0;
                while (i < m && !dp[i]) ++i;
                while (i < m) dp[i++] = true;
            }
        }
        return dp[m];
    }
};

 

你可能感兴趣的:(LeetCode)