[LeetCode] 44. Wildcard Matching
Given an input string (s
) and a pattern (p
), implement wildcard pattern matching with support for '?'
and '*'
where:
'?'
Matches any single character.'*'
Matches any sequence of characters (including the empty sequence).
The matching should cover the entire input string (not partial).
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'.
Constraints:
0 <= s.length, p.length <= 2000
s
contains only lowercase English letters.p
contains only lowercase English letters,'?'
or'*'
.
通配符匹配。
给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/wildcard-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题意是给两个字符串 s 和 p,其中 p 是带有通配符的。请你返回 p 是否能根据通配符的规则匹配 s。其中
'?' 可以匹配任何单个字符。 '*' 可以匹配任意字符串(包括空字符串)
思路是动态规划。这个题也有双指针的做法但是个人感觉动态规划的做法更好记。
首先定义动态规划的方程是 dp[i][j],定义是 s 的前 i 个字符和 p 的前 j 个字符是否相配。
初始化
- dp[0][0]:什么都没有,所以为 true
- 第一行dp[0][j],换句话说,s 为空,与 p 匹配,所以只要 p 开始为 * 才为 true
- 第一列dp[i][0],当然全部为 false
转移方程
- 如果(s[i] == p[j] || p[j] == "?") && dp[i-1][j-1] ,有 dp[i][j] = true
- 如果p[j] == "*" && (dp[i-1][j] = true || dp[i][j-1] = true) 有 dp[i][j] = true
note:
- dp[i][j-1],表示 * 代表是空字符,例如 ab,ab*
- dp[i-1][j],表示 * 代表非空任何字符,例如abcd,ab*
时间O(mn)
空间O(mn)
Java实现
1 class Solution { 2 public boolean isMatch(String s, String p) { 3 int m = s.length(); 4 int n = p.length(); 5 boolean[][] dp = new boolean[m + 1][n + 1]; 6 dp[0][0] = true; 7 for (int i = 1; i <= n; i++) { 8 dp[0][i] = dp[0][i - 1] && p.charAt(i - 1) == '*'; 9 } 10 for (int i = 1; i <= m; i++) { 11 for (int j = 1; j <= n; j++) { 12 if (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') { 13 dp[i][j] = dp[i - 1][j - 1]; 14 } else if (p.charAt(j - 1) == '*') { 15 dp[i][j] = dp[i - 1][j] || dp[i][j - 1]; 16 } 17 } 18 } 19 return dp[m][n]; 20 } 21 }
JavaScript实现
1 /** 2 * @param {string} s 3 * @param {string} p 4 * @return {boolean} 5 */ 6 var isMatch = function (s, p) { 7 let m = s.length; 8 let n = p.length; 9 let dp = [...Array(m + 1)].map((item) => Array(n + 1).fill(0)); 10 dp[0][0] = true; 11 for (let i = 1; i <= n; i++) { 12 dp[0][i] = dp[0][i - 1] && p.charAt(i - 1) == '*'; 13 } 14 for (let i = 1; i <= m; i++) { 15 for (let j = 1; j <= n; j++) { 16 if ( 17 s.charAt(i - 1) === p.charAt(j - 1) || 18 p.charAt(j - 1) === '?' 19 ) { 20 dp[i][j] = dp[i - 1][j - 1]; 21 } else if (p.charAt(j - 1) === '*') { 22 dp[i][j] = dp[i - 1][j] || dp[i][j - 1]; 23 } 24 } 25 } 26 return dp[m][n]; 27 };