[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 };

 

LeetCode 题目总结

posted @ 2020-06-02 04:30  CNoodle  阅读(458)  评论(0)    收藏  举报