LC44. Wildcard Matching

Implement wildcard pattern matching with support for '?' and '*'.

Posted by freeCookie🍪 on January 2, 2017

LC44. 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

这题和LC10. Regular Expression很像,都是String的匹配。但是区别在于这题的*是可以匹配任何Series,和其前面的char无关。’?’和’.’ 的作用相同。

two pointers solution

O(n) time and O(1) space

LC10我想用双指针结果交了无数次没有AC…这里由于*和前面的字符没有关系所以用双指针可解。分为几种情况,如果匹配则进行下一个字符的匹配,如果遇到🌟的话就记录当前位置并继续匹配,如果不匹配就回到上一个🌟的位置,改变🌟匹配series的长度继续匹配。

public class Solution {
    public boolean isMatch(String s, String p) {
        // two pointers
        if(s == null || p == null)  return false;
        char[] sarr = s.toCharArray();
        char[] parr = p.toCharArray();
        int i = 0, j = 0, star = -1, begin = 0;
        while(i < sarr.length){
            // if match or ?
            if(j < parr.length && (sarr[i] == parr[j] || parr[j] == '?')){
                i++;
                j++;
            // * match until not match, if not match backtracking to next char
            }else if(j < parr.length && parr[j] == '*'){
                while(j < parr.length && parr[j] == '*') j++;
                if(j == parr.length)    return true;  // last is *
                star = j;
                begin = i;
            // when * and not match
            }else if(star >= 0){
                i = ++begin;
                j = star;
            }else return false;
        } // while i,j
        while(j < parr.length && parr[j] == '*')    j++;
        return i == sarr.length && j == parr.length;
    }
}

其实我觉得这个不是O(n)…Backtracking最差的话会搞到O(n!)吧QAQ..事实证明two pointers的做法确实比DP快了很多。

⚠️:由于有可能匹配到最后p还有好多***但是s已经匹配完,所以while里是以s作为判断,最后再判断有可能有末尾的🌟存在。

DP solution

和LC10一样可以利用DP来解决, DP{i}{j}代表s[i-1]与p[j-1]是否匹配。初始化对于p前置*的DP矩阵都置为true。可以匹配时DP{i}{j} = DP{i-1}{j-1}, 遇到🌟时可能匹配一串字符或者不匹配字符,不匹配就对应DP{i}{j-1}, 一串则对应DP{i-1}{j}。

public class Solution {
    public boolean isMatch(String s, String p) {
        // DP
        if(s == null || p == null)  return false;
        char[] sarr = s.toCharArray();
        char[] parr = p.toCharArray();
        boolean[][] dp = new boolean[sarr.length+1][parr.length+1];
        dp[0][0] = true;
        for(int i = 1; i <= parr.length; i++){
            if(parr[i-1] == '*')  dp[0][i] = true; 
            else break;
        }
        for(int i = 1; i <= sarr.length; i++){
            for(int j = 1; j <= parr.length; j++){
                if(sarr[i-1] == parr[j-1] || parr[j-1] == '?'){
                    dp[i][j] = dp[i-1][j-1];
                }else if(parr[j-1] == '*'){
                    dp[i][j] = dp[i-1][j] || dp[i][j-1];
                }
            } // for j
        } // for i
        return dp[sarr.length][parr.length];
    }
}

复杂度O(n^2), O(n^2), 这个解法也比较好理解。

⚠️:各处的“=”

没10个提交都不能AC的QAQ