当前位置: 首页 > news >正文

力扣44题通配符匹配题解

44. 通配符匹配 - 力扣(LeetCode)

给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 '?''*' 匹配规则的通配符匹配:

  • '?' 可以匹配任何单个字符。
  • '*' 可以匹配任意字符序列(包括空字符序列)。

判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 0 <= s.length, p.length <= 2000
  • s 仅由小写英文字母组成
  • p 仅由小写英文字母、'?''*' 组成

题解

题目描述:给你两个字符串s文本字符串和p模式字符串,其中p包含两种类型的通配符:

  • *:可以匹配任意字符序列(包括空序列)
  • ?:可以匹配任意单个字符

题目要求你检查sp是否匹配。

Example 1:

  • s = "adceb"
  • p = "*a*b"
  • Output: true
  • Explanation: The first * can match an empty sequence, and the second * matches “dce”.

Example 2:

  • s = "acdcb"
  • p = "a*c?b"
  • Output: false
  • Explanation: There is no way to match s with p, as the character before the last in s is ‘c’ but ‘b’ in p.

这个题用贪心的思路该如何去想呢,在每一步匹配中,我们可以对如何匹配字符串做出局部最优选择,如*,可以表示任何字符序列,包括空序列,可以在匹配字符串的过程中及时调整匹配。

  • 对于?:由于?只匹配一个字符,即自动选择s的当前字符与p中的?匹配。
  • 对于*:因为他可以匹配任意字符序列,所以按照贪心的思路,首先用空序列匹配*,然后,如果需要,根据模式和字符串其余部分扩展或缩小匹配的字符数量。

贪心算法的实现思路

  1. 两个指针+回溯:首先定义两个指针,分别是ssIdx)和ppIdx),进行模式匹配,如果出现不匹配,则回溯到p*的最后一个位置(如果有),并尝试不同的匹配。
  2. ?通配符处理:在迭代中,如果 sp 中的当前字符匹配,或者 p[pIdx]? ,只需将两个指针向前移动。
  3. 处理*通配符:如果p*,需要分别标记*p中的位置(用starIdx),和在s中的对应位置(sTmpIdx表示)。表示*匹配s中的空字符的起点。如果稍后出现不匹配,则回溯到starIdx并增加sTmpIdx,表示*现在应该在s中多匹配一个字符。将pIdx重置为starIdx+1,将 sIdx 重置为 sTmpIdx ,继续匹配。
  4. 最后检查:遍历 s 后,确保 p 中所有剩余的字符都是 * 。如果是,它们可以匹配空序列,因此,模式匹配字符串。

具体示例

Consider :s = "adceb" and p = "*a*b"

Initial Setup

  • s = "adceb"
  • p = "*a*b"
  • sIdx = 0, pIdx = 0, starIdx = -1, sTmpIdx = -1

Iteration 1

  • p[0] is *, so we update starIdx = 0 and sTmpIdx = 0.
  • Increment pIdx to 1.
  • sIdx remains 0.

Iteration 2

  • p[1] is 'a', but s[0] is 'a'. This is a mismatch.
  • Since starIdx != -1, we use the star to match one more character.
  • Increment sTmpIdx to 1. So sTmpIdx = 1.
  • Update pIdx = starIdx + 1, which means pIdx = 1.
  • Update sIdx = sTmpIdx, which means sIdx = 1.

Iteration 3

  • Now p[1] is 'a' and s[1] is also 'a'. This is a match.
  • Increment both sIdx and pIdx by 1.
  • sIdx = 2, pIdx = 2.

Iteration 4

  • p[2] is '*'. Update starIdx = 2 and sTmpIdx = 2.
  • Increment pIdx to 3.
  • sIdx remains 2.

Iteration 5

  • p[3] is 'b', but s[2] is 'd'. This is a mismatch.
  • Since starIdx != -1, we use the star to match one more character.
  • Increment sTmpIdx to 3. So sTmpIdx = 3.
  • Update pIdx = starIdx + 1, which means pIdx = 3.
  • Update sIdx = sTmpIdx, which means sIdx = 3.

Iteration 6

  • p[3] is 'b' and s[3] is 'c'. This is a mismatch.
  • We repeat the backtracking process:
  • Increment sTmpIdx to 4. So sTmpIdx = 4.
  • Update pIdx = starIdx + 1, which means pIdx = 3.
  • Update sIdx = sTmpIdx, which means sIdx = 4.

Iteration 7

  • p[3] is 'b' and s[4] is 'b'. This is a match.
  • Increment both sIdx and pIdx by 1.
  • sIdx = 5, pIdx = 4.

Final Check

  • sIdx is now equal to s.size(), so we exit the while loop.
  • Check remaining characters in p. Since pIdx is also at the end of p, there are no more characters to check.
class Solution {
public:bool isMatch(string s, string p) {int sIdx = 0, pIdx = 0;      // Pointers for s and p.int starIdx = -1, sTmpIdx = -1;  // Indices to track the most recent '*' position in p and the corresponding position in s.while (sIdx < s.size()) {// If the characters match or pattern has '?', move both pointers.if (pIdx < p.size() && (p[pIdx] == s[sIdx] || p[pIdx] == '?')) {++sIdx;++pIdx;}// If pattern has '*', record the position and assume it matches zero characters initially.else if (pIdx < p.size() && p[pIdx] == '*') {starIdx = pIdx;sTmpIdx = sIdx;++pIdx;}// If a mismatch occurs and there was a previous '*', backtrack.// Try to match '*' with one more character in s.else if (starIdx != -1) {pIdx = starIdx + 1;sIdx = ++sTmpIdx;}// If no '*' to backtrack to, return false.else {return false;}}// Check if the remaining characters in pattern are all '*'.// They can match the empty sequence at the end of s.for (; pIdx < p.size(); ++pIdx) {if (p[pIdx] != '*') {return false;}}// If we've processed both strings completely, it's a match.return true;}
};
http://www.lryc.cn/news/256855.html

相关文章:

  • windows系统安装RocketMQ_dashboard
  • ATECLOUD电源自动测试系统打破传统 助力新能源汽车电源测试
  • 如何教会小白使用淘宝API接口获取商品数据
  • Redis有序集合对象
  • 【C++数据结构 | 字符串速通】10分钟秒杀字符串相关操作 | 字符串的增删改查 | 字符串与数组相互转换
  • 运动重定向:C-3PO
  • 天池SQL训练营(四)-集合运算-表的加减法和join等
  • thinkphp lists todo
  • 【Flutter】创建应用顶级组件,应用根组件 (学习记录)
  • AI材料专题报告:AI革命催生新需求国产替代推动新方向
  • JVM 分析GC日志
  • 阿里云服务器环境配置,ssh免密登录和配置docker
  • 【LeetCode】2621. 睡眠函数
  • 网络入门---TCP通信实现
  • neuq-acm预备队训练week 8 P2661 [NOIP2015 提高组] 信息传递
  • 《C++新经典设计模式》之第18章 备忘录模式
  • OWASP安全练习靶场juice shop-更新中
  • 当使用RSA加密,从手机前端到服务器后端的请求数据存在+
  • BUUCTF crypto做题记录(3)新手向
  • SpringMVC修炼之旅(2)基础入门
  • matlab 最小二乘拟合空间直线(方法二)
  • ASPICE-汽车软件开发能力评级
  • 准确!!!在 CentOS 8 上配置 PostgreSQL 14 的主从复制
  • leetcode 1466
  • 想学编程,但不知道从哪里学起,应该怎么办?
  • Python数据科学视频讲解:Python概述
  • 数据结构之内部排序
  • 软考高级备考-系统架构师(机考后新版教材的备考过程与资料分享)
  • Spring Boot 整合kafka:生产者ack机制和消费者AckMode消费模式、手动提交ACK
  • Java+Swing: 主界面组件布局 整理9