LeetCode 44. 通配符匹配

给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 ‘?‘ 和 ‘*‘ 的通配符匹配。

‘?‘ 可以匹配任何单个字符。
‘*‘ 可以匹配任意字符串(包括空字符串)。

两个字符串完全匹配才算匹配成功。

说明:

  • s 可能为空,且只包含从 a-z 的小写字母。
  • p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:
s = "aa"
p = "*"
输出: true
解释: ‘*‘ 可以匹配任意字符串。

示例 3:

输入:
s = "cb"
p = "?a"
输出: false
解释: ‘?‘ 可以匹配 ‘c‘, 但第二个 ‘a‘ 无法匹配 ‘b‘。

示例 4:

输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 ‘*‘ 可以匹配空字符串, 第二个 ‘*‘ 可以匹配字符串 "dce".

示例 5:

输入:
s = "acdcb"
p = "a*c?b"
输入: false

这个题在很多个Tag下,如DP,贪心,回溯等。

动态规划

对于两个字符串的问题,容易想到用dp[i][j]这样的形式来表示状态。我一开始是定义dp[i][j]为字符串s中前i个字符和p中前j个字符是否匹配(i和j从0开始),由于初始化问题弄了很久,最后写出的代码异常垃圾。。。

class Solution {
public:
    bool isMatch(string s, string p) {
        if (p.size() == 0 && s.size() == 0) {
            return true;
        }
        if (p.size() == 0) {
            return false;
        }
        else if (p == "*") {
            return true;
        }
        else if (s.size() == 0) {
            return false;
        }
        int row = p.size(), column = s.size();
        vector<vector<int>> dp(row);
        vector<bool> okDp(row, false);
        for (int i = 0; i < row; i++) {
            dp[i].resize(column);
        }
        bool matched = false;
        dp[0][0] = (p[0] == ‘*‘ || p[0] == ‘?‘ || p[0] == s[0]) ? 1 : 0;
        if (p[0] == ‘?‘ || p[0] == s[0]) {
            matched = true;
        }
        for (int i = 1; i < row; i++) {
            if (p[i] == ‘*‘) {
                dp[i][0] = dp[i - 1][0];
                if (dp[i][0]) {
                    okDp[i] = true;
                }
            }
            else if (p[i - 1] == ‘*‘ && p[i] == s[0]) {
                dp[i][0] = matched ? 0 : dp[i - 1][0];
                matched = true;
            }
            else if (p[i] == ‘?‘) {
                dp[i][0] = matched ? 0 : dp[i - 1][0];
                matched = true;
            }
        }
        for (int j = 1; j < column; j++) {
            if (p[0] == ‘*‘) {
                dp[0][j] = 1;
            }
        }
        for (int i = 1; i < row; i++) {
            for (int j = 1; j < column; j++) {
                if (isalpha(s[j]) && isalpha(p[i])) {
                    if (s[j] == p[i]) {
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                    else {
                        dp[i][j] = 0;
                    }
                }
                else if (p[i] == ‘?‘) {
                    dp[i][j] = dp[i - 1][j - 1];
                }
                else if (p[i] == ‘*‘) {
                    if (okDp[i] || dp[i - 1][j]) {
                        okDp[i] = true;
                        dp[i][j] = 1;
                    }
                }
            }
        }
        return dp[row - 1][column - 1];
    }
};

后来学习了其他的解法,先上代码:

class Solution {
public:
    bool isMatch(string s, string p)
    {
        int n=s.size();
        int m=p.size();
        //代表的是  s[0...i]  p[0..j]是否匹配的情况
        vector<vector<bool>>dp(n+1,vector<bool>(m+1,false));
        dp[0][0]=true;
        for(int j=1;j<=m;j++)
            dp[0][j]=(p[j-1]==‘*‘?dp[0][j-1]:0);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(i>0&&(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-1]||dp[i-1][j]||dp[i][j-1];
                }
                else
                    dp[i][j]=0;
            } 

        return dp[n][m];
    }

};

在这里,状态dp[i][j]是从1开始计算起来的。一开始不明白为什么这样子也行得通,后来考虑到有空串的情况。如""和""对于dp[0][0],""和"*"对于dp[0][1]。这样子的话初始化就很容易了。

在填表的过程中:

  1. 如果s[i - 1] = p[j - 1],则是字母匹配到了字母,那么匹配结果取决于前面的匹配结果。
  2. 如果p[j - 1] = ‘?‘,那么是问号匹配到了字母,也是匹配结果取决于前面的结果。
  3. 如果p[j - 1] = ‘*’,那么是遇到了星号。星号可能匹配的是空串,那么就是取决于dp[i][j - 1]的结果。如果匹配了一个字符,那么就是取决于dp[i - 1][j - 1]。如果匹配了两个字符,那么就是取决于dp[i - 2][j - 1]。
    所以,dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 2][j - 1] || ... || dp[0][j - 1]。
    又因为dp[i - 1][j] = dp[i - 1][j - 1] || dp[i - 2][j - 1] || ... || dp[0][j - 1]。
    所以dp[i][j] = dp[i][j - 1] || dp[i - 1][j]。

原文地址:https://www.cnblogs.com/hlk09/p/9748225.html

时间: 2024-10-15 01:21:48

LeetCode 44. 通配符匹配的相关文章

LeetCode 44. 通配符匹配(Wildcard Matching)

题目描述 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配. '?' 可以匹配任何单个字符. '*' 可以匹配任意字符串(包括空字符串). 两个字符串完全匹配才算匹配成功. 说明: s 可能为空,且只包含从 a-z 的小写字母. p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *. 示例 1: 输入: s = "aa" p = "a" 输出: false 解释: "a" 无法匹配 &

leetcode 44 通配符匹配(dp)

思路: 思路一: 利用两个指针进行遍历. 在代码里解释. 时间复杂度为:O(mn)O(mn)O(mn) 思路二: 动态规划 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][

leetcode 44 字符匹配

题意:s是空串或包含a-z字母: p为包含a-z字母或?或 * (其中*可以匹配任意字符串包括空串,?可以匹配任意字符). 思路: 1)特殊情况:当s为空串时,p为连续 * 时,则连续 * 的位置都为true. 2)若p的第j个字符为 * ,分两种情况: a)  若p中的前 j-1个字符和 s 中的前 i 个字符匹配成功了, 即 dp[i][j-1] == true , 因为 * 可以匹配空串,则 dp[i][j] == true; b)  若p中的前 j 个字符和 s 中前 i-1 个字符匹配

44. 通配符匹配

题目描述查看:https://leetcode-cn.com/problems/wildcard-matching/ 题目的意思是给一个字符串s,给一个模式串p,要看p和s匹不匹配.模式串里可以出现'?',匹配一个任意字符:可以出现'*',匹配0个或多个任意字符. 思路 创建一个数组dp[i][j]用来保存模式串p中的前i个字符和字符串s中的前j个字符匹不匹配. dp[0][0]表示p中0个字符和s中0个字符匹不匹配,显然匹配. dp[0][0] = true; dp[0][i]表示p中0个字符

Leetcode44. 通配符匹配(动态规划)

44. 通配符匹配 动态规划 \(f_{i,j}\)为\(s\)匹配\(i\),\(t\)匹配\(j\)是否成功 贪心 相比之下这个思维性更强 考虑两个*,两个星号间的过渡,只需要过渡完到第二个星号,第一个星号匹配多少已经无所谓了 所以贪心的处理已经匹配到的之前的最后一个星号的匹配个数 Code(copy) class Solution { public: bool isMatch(string s, string p) { int i = 0; int j = 0; int star = -1

LeetCode(44): 通配符匹配

Hard! 题目描述: 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配. '?' 可以匹配任何单个字符. '*' 可以匹配任意字符串(包括空字符串). 两个字符串完全匹配才算匹配成功. 说明: s 可能为空,且只包含从 a-z 的小写字母. p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *. 示例 1: 输入: s = "aa" p = "a" 输出: false 解释: "a"

(Java) 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 enti

[LeetCode] Wildcard Matching 通配符匹配

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). The function p

第八周 Leetcode 44. Wildcard Matching 水题 (HARD)

Leetcode 44 实现一种类似正则表达式的字符串匹配功能. 复杂度要求不高, 调代码稍微费点劲.. 好像跟贪心也不太沾边, 总之 *把待匹配串分成若干个子串, 每一个子串尽量在模式串中靠前的部分匹配完成就算贪心了吧.. class Solution { public: bool match(string &s,string &p,int l2,int r2,int l1) { if(l2==r2)return true; if(l1+r2-l2-1>=s.length())re