44. Wildcard Matching

Problem:
Given an input string (s) and a pattern (p), 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).
Note:
  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like ? or *.
Example 1:
Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input:
s = "aa"
p = "*"
Output: true
Explanation: '*' matches any sequence.
Example 3:
Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
Example 4:
Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
Example 5:
Input:
s = "acdcb"
p = "a*c?b"
Output: false
5/28/2018 update:
Another approach uses DP.
dp[i][j]: whether s.substring(0, i) matches p.substring(0, j).

case 1 : s[i - i] == p[j - 1] or p[j - 1] == '?'
             char s[i - 1] and char p[j - 1] matches, dp[i][j] = dp[i - 1][j - 1]
case 2: p[j - 1] == '*'
             * represents empty sequence we check dp[i][j - 1]
             * extends to s[i - 1] we check dp[i - 1][j]


''a*c?b
''TFFFFF
aFTTFFF
cFFTTFF
dFFTFTF
cFFTTFF
bFFTFTF

The initialization is tricky here. dp[0][0] is true, then we check first row and first column. First column are all false except the [0,0]. First row determines by p[i] == '*'. dp[0][j] = dp[0][j - 1], here * represents empty. Go up means * extends s[i - 1], there is no way to go up as row 0.
class Solution {
    public boolean isMatch(String s, String p) {
        char[] S = s.toCharArray();
        char[] P = p.toCharArray();
        int m = s.length();
        int n = p.length();
        boolean[][] dp = new boolean[m + 1][n + 1];
        dp[0][0] = true;
        for (int j = 1; j <= n; j++) {
            if (P[j - 1] == '*')
                dp[0][j] = dp[0][j - 1];
        }
        
        for (int i = 1; i <= m; i++) 
            for (int j = 1; j <= n; j++) {
                if (S[i - 1] == P[j - 1] || P[j - 1] == '?') {
                    dp[i][j] = dp[i - 1][j - 1];                    
                }
                else if (P[j - 1] == '*') {
                    dp[i][j] = dp[i - 1 ][j] || dp[i][j - 1];   
                }
            }
        
        return dp[m][n];
    }
}
--------------------------------------------------------------------------------------------------------------------------
5/26/2018 update:
When we encounter '*',  pp++ is easier to understand this time. As stated last time below, we only care about what is after start, so we compare p.charAt(++pp) with s.

For the case
S: "acdcb"
P: "a*c?b"

acdcb
sp
a*c?b
pp
acdcb

sp
a*c?b
pp

We encounter * then find c in S. Then continue, sp and pp are not matching. Since there is a star, we have more chances to shoot. From the old match position +1, we try to find c in S again.

Why not put pp < p.length() to the while condition? Because when we reach the end of P, it's possible S's end haven't be reached. Like the case S:"aa", P: "a".
--------------------------------------------------------------------------------------------------------------------------
Analysis:
Match s and p character by character.

 If we meet *, we care about the char after * in P. Then try to find that char in S.
S: abcde
P: a*e
We compare bcd in S with e in P. So we need to know the position of  '*', the start position of S match.

Solution:
If we don't increment pp when we encounter *, we will fall into infinite loop.
class Solution {
    public boolean isMatch(String s, String p) {
        int sp = 0, pp = 0, star = -1, match = 0;
        while (sp < s.length()) {
            if (pp < p.length() && (s.charAt(sp) == p.charAt(pp) || p.charAt(pp) == '?')) {
                sp++;
                pp++;
            } else if (pp < p.length() && p.charAt(pp) == '*') {
                star = pp;
                match = sp;
                pp++;
            } else if (star != -1) {
                pp = star + 1;
                match++;
                sp = match;
            } else {
                return false;
            }
        }
        while (pp < p.length() && p.charAt(pp) == '*') {
            pp++;
        }
        return pp == p.length();
    }
}

评论

此博客中的热门博文

663. Equal Tree Partition

776. Split BST

426. Convert Binary Search Tree to Sored Doubly Linked List