LeetCode解题 44:Wildcard Matching(动态规划解法)
Problem 44: Wildcard Matching [Hard]
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: false
来源:LeetCode
解题思路
与题解10:Regular Expression Matching,使用动态规划思想。维护数组match[n][m],match[i][j]代表字符串s
的前i个和模式p
的前j个是否匹配。二重循环遍历s
和p
,match[i][j]根据p[j]和s[i]的关系可以由match[i-1][j-1]等前项转换而来,具体转换公式为:
-
当 p [ j ] = s [ i ] p[j] = s[i] p[j]=s[i] 或者 p [ j ] = p[j] = p[j]=
'?'
时,有
m a t c h [ i ] [ j ] = m a t c h [ i − 1 ] [ j − 1 ] match[i][j] = match[i-1][j-1] match[i][j]=match[i−1][j−1] -
当 p [ j ] = p[j] = p[j]=
'*'
时,*
有可能匹配零个字符或多个字符。假设当前s
为###
,p
为###*
,则match[i][j]有可能从不同的前项转移而来:i.
*
匹配多个字符的情况,例如:czhcb|a
和czh|*
。此时s[i]上的a
只是*
的延续,转移公式为:
m a t c h [ i ] [ j ] = m a t c h [ i − 1 ] [ j ] match[i][j] = match[i-1][j] match[i][j]=match[i−1][j]
注意:除了上述例子中*
匹配了三个字符cba
的情况,转移公式同样适用于匹配一个字符的情况。(s =czhcb|a
,p =czhcb|*
,match[i-1][j]代表czhcb
和czhcb*
匹配,多一个a后仍然相当于a
只是*
的延续,因此不需要特意考虑match[i-1][j-1]的值。)ii.
*
匹配零个字符的情况,例如:czh|a
和czha|*
。此时*
是多余的,可以去掉,转移公式为:
m a t c h [ i ] [ j ] = m a t c h [ i ] [ j − 1 ] match[i][j] = match[i][j-1] match[i][j]=match[i][j−1]
情况i和情况ii中,只要任意一个能匹配上,则 m a t c h [ i ] [ j ] = t r u e match[i][j] = true match[i][j]=true。 -
当 p [ j ] p[j] p[j]不属于上述任何情况,即 p [ j ] p[j] p[j]不为特殊符号且 p [ j ] ≠ s [ i ] p[j] \neq s[i] p[j]=s[i]时, m a t c h [ i ] [ j ] = f a l s e match[i][j] = false match[i][j]=false。
时间复杂度为 O ( n m ) O(nm) O(nm),空间复杂度为 O ( n m ) O(nm) O(nm)。
运行结果:
要点:动态规划
Solution (Java)
class Solution {
public boolean isMatch(String s, String p) {
int n = s.length() + 1;
int m = p.length() + 1;
if(n == 1 && m == 1) return true;
if(n > 1 && m == 1) return false;
boolean[][] match = new boolean[n][m];
// initialize
match[0][0] = true;
for(int mj = 1; mj < m; mj++){
int j = mj - 1;
if(p.charAt(j) == '*') match[0][mj] = match[0][mj-1];
else match[0][mj] = false;
}
for(int mi = 1; mi < n; mi++){
match[mi][0] = false;
}
// dp
for(int mi = 1; mi < n; mi++){
for(int mj = 1; mj < m; mj++){
int i = mi - 1;
int j = mj - 1;
if(p.charAt(j) == s.charAt(i) || p.charAt(j) == '?'){
match[mi][mj] = match[mi-1][mj-1];
}
else if(p.charAt(j) == '*'){
match[mi][mj] = match[mi-1][mj] || match[mi][mj-1];
}
else{
match[mi][mj] = false;
}
}
}
return match[n-1][m-1];
}
}