LeetCode-44-通配符匹配

在这里插入图片描述

1、递归

具体思路同LeetCode-剑指19-正则表达式匹配,但在本题中由于字符串长度过长会导致超时。

在这里插入代码片class Solution {
public:
    bool isMatch(string s, string p) {
        if (p.empty()) return s.empty();
        bool first_match = !s.empty() && (s[0] == p[0] || p[0] == '?' || p[0] == '*');
        if (p[0] == '*') {
            return (first_match && isMatch(s.substr(1), p)) || isMatch(s, p.substr(1));
        } else {
            return first_match && isMatch(s.substr(1), p.substr(1));
        }
    }
};

2、动态规划法

我们可以利用二维数组 d p [ i ] [ j ] dp[i][j] dp[i][j]来表示字符串 s s s的前 i i i位与字符串 p p p的前 j j j位的匹配情况。我们首先需要对二维数组进行初始化,其中 d p [ 0 ] [ 0 ] = t r u e dp[0][0] = true dp[0][0]=true,当字符串 p p p的前 j j j位均为 “ ∗ ” “*” 时同样 d p dp dp值为 t r u e true true。而后我们进行循环:1、若 p [ j − 1 ] = = ′ ? ′ 或 s [ i − 1 ] = = p [ j − 1 ] p[j - 1] == '?' 或 s[i - 1] == p[j - 1] p[j1]==?s[i1]==p[j1],说明此时这一位上两个字符串是匹配的,故具体的值取决于此前的字符串是否匹配;2、若 p [ j − 1 ] = = ′ ∗ ′ p[j - 1] == '*' p[j1]==,说明此时可能出现两种情况,一是 “ ∗ ” “*” 匹配空字符串,故此时的状态与 d p [ i ] [ j − 1 ] dp[i][j - 1] dp[i][j1]相同,二是 “ ∗ ” “*” 匹配任意一个字符,此时的状态与 d p [ i − 1 ] [ j ] dp[i - 1][j] dp[i1][j]的状态相同。

class Solution {
public:
    bool isMatch(string s, string p) {
        vector<vector<bool>> dp(s.size() + 1, vector<bool>(p.size() + 1));
        dp[0][0] = true;
        for (int i = 1; i <= p.size(); ++i) {
            if (p[i - 1] == '*') dp[0][i] = true;
            else break;
        }
        for (int i = 1; i <= s.size(); ++i) {
            for (int j = 1; j <= p.size(); ++j) {
                if (p[j - 1] == '?' || s[i - 1] == p[j - 1]) dp[i][j] = dp[i - 1][j - 1];
                if (p[j - 1] == '*') dp[i][j] = dp[i][j - 1] | dp[i - 1][j];
            }
        }
        return dp[s.size()][p.size()];
    }
};

3、贪心算法

我们可以将字符串 p p p认为是可以根据 “ ∗ ” “*” 分割后的多个字符串,若在原来的字符串 s s s中包含这些字符串则说明两个字符串是匹配的。在此我们还需要考虑两种特殊情况:1、字符串 p p p不以 “ ∗ ” “*” 作为结尾,此时我们可以先从后向前进行遍历直至以 “ ∗ ” “*” 作为结尾;2、字符串 p p p不以 “ ∗ ” “*” 作为开头,此时我们利用 s R e c o r d sRecord sRecord t R e c o r d tRecord tRecord标记为-1表示不能继续重新匹配。

class Solution {
public:
    bool isMatch(string s, string p) {
        auto allStars = [](const string& str, int left, int right) {
            for (int i = left; i < right; ++i) {
                if (str[i] != '*') {
                    return false;
                }
            }
            return true;
        };
        auto charMatch = [](char u, char v) {
            return u == v || v == '?';
        };

        while (s.size() && p.size() && p.back() != '*') {
            if (charMatch(s.back(), p.back())) {
                s.pop_back();
                p.pop_back();
            }
            else {
                return false;
            }
        }
        if (p.empty()) {
            return s.empty();
        }

        int sIndex = 0, pIndex = 0;
        int sRecord = -1, pRecord = -1;
        while (sIndex < s.size() && pIndex < p.size()) {
            if (p[pIndex] == '*') {
                ++pIndex;
                sRecord = sIndex;
                pRecord = pIndex;
            }
            else if (charMatch(s[sIndex], p[pIndex])) {
                ++sIndex;
                ++pIndex;
            }
            else if (sRecord != -1 && sRecord + 1 < s.size()) {
                ++sRecord;
                sIndex = sRecord;
                pIndex = pRecord;
            }
            else {
                return false;
            }
        }
        return allStars(p, pIndex, p.size());
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值