LeetCode 44 Wildcard Matching (通配符匹配 记忆化搜索 剪枝 推荐)

2023-11-05

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

题目链接:https://leetcode.com/problems/wildcard-matching/

题目分析:与正则匹配比较类似,本题不用记忆化会直接超时,多个连续的'*'可直接缩成1个,功能不会产生变化

25ms,时间击败76.9% (运行时间不是很稳定,21ms~28ms)

class Solution {
    
    public boolean isFirstPosMatch(String s, int spos, String p, int ppos) {
        return (spos < s.length() &&
            (s.charAt(spos) == p.charAt(ppos) ||
             p.charAt(ppos) == '?'));
    }
    
    public boolean isMatch(String s, String p) {
        int[][] match = new int[s.length() + 2][p.length() + 2];
        return isMatchHelper(s, 0, p, 0, match);
    }
    
    public boolean isMatchHelper(String s, int spos, String p, int ppos, int[][] match) {
        if (match[spos][ppos] != 0) {
            return match[spos][ppos] == 1;
        }
        if (ppos == p.length()) {
            match[spos][ppos] = spos == s.length() ? 1 : -1;
            return match[spos][ppos] == 1;
        }
        if (p.charAt(ppos) != '*') {
            match[spos][ppos] = isFirstPosMatch(s, spos, p, ppos) && isMatchHelper(s, spos + 1, p, ppos + 1, match) ? 1 : -1;
            return match[spos][ppos] == 1;
        }
        while (ppos < p.length() && p.charAt(ppos) == '*') {
            ppos++;
        }
        while (spos < s.length()) {
            match[spos][ppos] = isMatchHelper(s, spos, p, ppos, match) ? 1 : -1;
            if (match[spos][ppos] == 1) {
                return true;
            }
            spos++;
        }
        match[spos][ppos] = isMatchHelper(s, spos, p, ppos, match) ? 1 : -1;
        return match[spos][ppos] == 1;
    }
}

最后的while循环看上去是比较耗时的,可以从中挖掘一些剪枝,通配符匹配和正则匹配的一大不同就是通配符匹配中模式串的确定字符必须要在主串上严格匹配(正则可通过'*'消去前一项),于是想到用两个cnt数组分别记录s和p中字符串的个数,设当前匹配到了s的第i项s[i],若pcnt[s[i]] > scnt[s[i]],则说明s串接下来的s[i]字符已不够p串匹配了,故此时的'*'不能消掉s[i]

加了这个剪枝后,6ms,时间击败97.9%

class Solution {
    
    public boolean isFirstPosMatch(String s, int spos, String p, int ppos) {
        return (spos < s.length() &&
            (s.charAt(spos) == p.charAt(ppos) ||
             p.charAt(ppos) == '?'));
    }
    
    public boolean isMatch(String s, String p) {
        int[] scnt = new int[26];
        int[] pcnt = new int[26];
        for (int i = 0; i < s.length(); i++) {
            scnt[s.charAt(i) - 'a']++;
        }
        for (int i = 0; i < p.length(); i++) {
            char ch = p.charAt(i);
            if (ch >= 'a' && ch <= 'z') {
                pcnt[ch - 'a']++;
            }
        }
        int[][] match = new int[s.length() + 2][p.length() + 2];
        return isMatchHelper(s, 0, p, 0, match, scnt, pcnt);
    }
    
    public boolean isMatchHelper(String s, int spos, String p, int ppos, int[][] match, int[] scnt, int[] pcnt) {
        if (match[spos][ppos] != 0) {
            return match[spos][ppos] == 1;
        }
        if (ppos == p.length()) {
            match[spos][ppos] = spos == s.length() ? 1 : -1;
            return match[spos][ppos] == 1;
        }
        if (p.charAt(ppos) != '*') {
            boolean ok = isFirstPosMatch(s, spos, p, ppos);
            if (ok) {
                scnt[s.charAt(spos) - 'a']--;
                if (p.charAt(ppos) != '?') {
                    pcnt[p.charAt(ppos) - 'a']--;
                }
                ok &= isMatchHelper(s, spos + 1, p, ppos + 1, match, scnt, pcnt);
                if (p.charAt(ppos) != '?') {
                    pcnt[p.charAt(ppos) - 'a']++;
                }
                scnt[s.charAt(spos) - 'a']++;
            }
            match[spos][ppos] = ok ? 1 : -1;
            return ok;
        }
        while (ppos < p.length() && p.charAt(ppos) == '*') {
            ppos++;
        }
        while (spos < s.length() && pcnt[s.charAt(spos) - 'a'] <= scnt[s.charAt(spos) - 'a']) {
            match[spos][ppos] = isMatchHelper(s, spos, p, ppos, match, scnt, pcnt) ? 1 : -1;
            if (match[spos][ppos] == 1) {
                return true;
            }
            scnt[s.charAt(spos) - 'a']--;   
            spos++;
        }
        match[spos][ppos] = isMatchHelper(s, spos, p, ppos, match, scnt, pcnt) ? 1 : -1;
        return match[spos][ppos] == 1;
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LeetCode 44 Wildcard Matching (通配符匹配 记忆化搜索 剪枝 推荐) 的相关文章

  • python 画正弦曲线

    要画正弦曲线先设定一下x的取值范围 从0到2 要用到numpy模块 numpy pi 表示 numpy arange 0 2 0 01 从0到2 以0 01步进 令 x numpy arange 0 2 numpy pi 0 01 y nu

随机推荐

  • 进程、线程和协程的理解

    进程 线程和协程的理解 进程 线程和协程之间的关系和区别也困扰我一阵子了 最近有一些心得 写一下 进程拥有自己独立的堆和栈 既不共享堆 亦不共享栈 进程由操作系统调度 线程拥有自己独立的栈和共享的堆 共享堆 不共享栈 线程亦由操作系统调度
  • 模拟模态对话框的DIV

    最近项目中用到一个模拟模态对话框的DIV的实现 有两个层 下面的层是半透明的 将遮盖整个窗口 上面的层则用于用户输入信息 这里是一个简单的模仿 以下是页面代码 table tr td td tr table
  • unity3D游戏开发三之unity编辑器二

    unity3D游戏开发三之unity编辑器二 分类 unity3d开发 2014 04 06 12 03 264人阅读 评论 0 收藏 举报 unity3d 游戏开发 编辑器 对象 下面我们介绍下GameObject 游戏对象 物体 通过游
  • uniapp 使用uView框架 upload组件上传前压缩图片

    根据Uview官方文档所说 若是小程序和app项目 上传使用压缩图片 可以配置u upload组件的sizeType属性为 compress 但这对H5是无效的 在实际开发中 图片压缩上传经常是一个必要的需求 所以本篇文章主要讲的是在H5项
  • 算法 - leetcode 292 Nim Game

    算法 leetcode 292 Nim Game 一丶题目 你和你的朋友 两个人一起玩 Nim 游戏 桌子上有一堆石头 每次你们轮流拿掉 1 3 块石头 拿掉最后一块石头的人就是获胜者 你作为先手 你们是聪明人 每一步都是最优解 编写一个函
  • 初级算法(字符串篇):报数

    题目描述 The count and say sequence is the sequence of integers with the first five terms as following 1 11 21 1211 111221 1
  • windows:升级node版本

    目录 1 打开DOS窗口 然后输入 node v 回车 2 输入 where node 查看node安装位置 3 下载你想安装的node版本的msi程序 4 安装步骤3中下载的文件 然后安装位置选择步骤2中的位置 比如步骤2中我的位置是 C
  • 每个人都能制作的简易版QQ音乐(HTML+CSS+JQuery)

    自制系列二它来了 如果在制作过程中有如何问题你都可以私信我 我会答复你的 今天中秋节 首先祝大家中秋节快乐 因为没什么礼物送给大家 所以在这里给大家安利一份简易版QQ音乐的制作 过程很简单 每个人都能学会 下面将是制作步骤了 先建好目录如下
  • 未将对象引用设置到对象的实例--可能出现的问题总结

    一 网络上的一般说法 1 ViewState 对象为Null 2 DateSet 空 3 sql语句或Datebase的原因导致DataReader空 4 声明字符串变量时未赋空值就应用变量 5 未用new初始化对象 6 Session对象
  • python代码使用cython进行加密

    python代码加密 前言 加密的多种方式 Cython加密 步骤 注意 部署 前言 加密的多种方式 发布编译过的pyc文件 缺点 很容易被反编译 PyInstaller 是一个用来将 Python 程序打包成一个独立可执行软件包 支持 W
  • 粉丝提问

    粉丝提问 c语言 如何定义一个和库函数名一样的函数 并在函数中调用该库函数 一个端口号可以同时被两个进程绑定吗 两个线程 两个互斥锁 怎么形成一个死循环 一个例子让你看清线程调度的随机性 问题描述 某个函数fun 1 是在lib内 没法修改
  • R语言:cbind()和rbind()

    可以利用函数cbind 和rbind 把向量和矩阵拼成一个新的矩阵 概略地说 cbind 把矩阵横向合并成一个大矩阵 列方式 而rbind 是纵向合并 行方式 cbind 根据列进行合并 即叠加所有列 m列的矩阵与n列的矩阵cbind 最后
  • ant design of vue 之文件上传组件(腾讯云)封装

    原理 通过调用后台接口获取腾讯云秘钥 然后将秘钥以及文件信息上传到腾讯云 获取文件腾讯云存储信息 最后组件将腾讯云存储信息返回出去 在组件外部调用后台接口将腾讯云信息存到后台 安装cos js sdk v5依赖 npm i cos js s
  • 2021数据治理工具图谱研究报告 附下载

    根据2021年4月发布的 国家数据资源调查报告 2020 显示 2019年我国数据产量总规模为3 9ZB 同比增加29 3 占全球数据总产量 42ZB 的9 3 人均数据产量方面 2019年我国人均数据产量为3TB 数据来源结构方面 数据资
  • 机器学习中的高斯过程

    0 前言 写这篇文章的目的就是为了总结一下最近在学习的高斯过程的一些内容 但是由于我是初学者可能有些地方理解不到位 请大家多多谅解 文末附上了一些数学方面的推导 1 高斯过程定义 高斯过程是在连续域上定义的一种随机过程 可以看成连续域中所有
  • vue中通过js把从接口取到的url中的{}里的参数替换成对应的值

    最近工作中遇到个需求 首先在一个页面中给按钮配置个点击跳转的链接 手动输入需要跳转的url及其需要的参数 后续要在另一个页面中通过接口取到配置的这个url 并替换掉当中的参数 第一次处理这种情况 所以记录一下 前端页面配置url 参数值通过
  • 【YOLO系列】YOLOv5超详细解读(网络详解)

    前言 吼吼 终于来到了YOLOv5啦 首先 一个热知识 YOLOv5没有发表正式论文哦 为什么呢 可能YOLOv5项目的作者Glenn Jocher还在吃帽子吧 hh 目录 前言 一 YOLOv5的网络结构 二 输入端 1 Mosaic数据
  • m118w重置墨粉_富士施乐 Fuji Xerox DocuPrint M118w/M118z重置墨粉页面计数器及重置硒鼓...

    富士施乐M118w的硒鼓和分仓是独立的 前几天M118w就提示墨粉已经不足 于是Pop就看了一下机器 打印了约1200张了 随机器来的原装可能就是这样而已 于是就了解了一下富士施乐M118w如何加粉 如何换硒鼓 以及如何清零重置硒鼓的操作
  • Mac os 10.14装virtualbox 失败的解决方案

    1 Mac 系统装virtualbox 失败如下 2 由于Mac 10 14的安全级别更高 所以导致这个软件安装过程失败 需要一下操作安装就没问题 2 1 开启通用里的允许任何来源 sudo spctl master disable 2 2
  • LeetCode 44 Wildcard Matching (通配符匹配 记忆化搜索 剪枝 推荐)

    Given an input string s and a pattern p implement wildcard pattern matching with support for and Matches any single char