• [LeetCode] 44. Wildcard Matching


    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

    通配符匹配。题意是给两个字符串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 题目总结

  • 相关阅读:
    欧拉法求乘率
    利用连分数求乘率
    反乘率
    乘率
    别害怕暂时的迷茫
    别害怕心中的理想
    HDU6072 Logical Chain
    P3345 [ZJOI2015]幻想乡战略游戏
    P4449 于神之怒加强版
    [笔记] 拉格朗日插值法
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13028948.html
Copyright © 2020-2023  润新知