44. Wildcard Matching
Problem:
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]
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.
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"
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.
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 lettersa-z
.p
could be empty and contains only lowercase lettersa-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: false5/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]
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"
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(); } }
评论
发表评论