力扣10.正则表达式匹配

news2024/11/27 17:54:44

前言:

由于今天面试前端,面试官问对正则表达式的匹配理解吗?

当时脑袋发热,我说就是对字符串的替换。。。。

太抽象了,于是我面试结束后马上打开力扣,解了正则表达式的匹配算法题(四种语言);

下面看题

题目:

解题思路: 

C语言: 

Python:

JavaScript: 

Java: 

总结: 


题目:

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

  • '.' 匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

 

示例 1:

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

示例 2:

输入:s = "aa", p = "a*"
输出:true
解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

示例 3:

输入:s = "ab", p = ".*"
输出:true
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。

提示:

  • 1 <= s.length <= 20
  • 1 <= p.length <= 20
  • s 只包含从 a-z 的小写字母。
  • p 只包含从 a-z 的小写字母,以及字符 . 和 *
  • 保证每次出现字符 * 时,前面都匹配到有效的字符

 

解题思路: 

这道题可以使用动态规划来解决。我们定义一个二维数组 dp,其中 dp[i][j] 表示字符串 s 的前 i 个字符是否与正则表达式 p 的前 j 个字符匹配。

我们首先初始化 dp[0][0] 为 true,因为空字符串总是与空正则表达式匹配。然后,我们遍历正则表达式 p 中的每个字符,并更新 dp 表。

如果当前字符是 '.', 则它可以匹配任何字符,因此我们更新 dp[i][j] 为 dp[i - 1][j - 1]。

如果当前字符是 '*', 则它可以匹配前面一个字符零次或多次。因此,我们更新 dp[i][j] 为 dp[i - 1][j - 1]、dp[i][j - 1] 和 dp[i][j] 的或。

如果当前字符是其他字符,则它必须与字符串 s 中的当前字符匹配。因此,我们更新 dp[i][j] 为 dp[i - 1][j - 1]。

最后,我们返回 dp[m][n],其中 m 和 n 分别是字符串 s 和正则表达式 p 的长度。如果 dp[m][n] 为 true,则字符串 s 与正则表达式 p 匹配,否则不匹配。

代码实现: 

 

C语言: 

bool isMatch(char *s, char *p) {
    int m = strlen(s);
    int n = strlen(p);
    bool dp[m + 1][n + 1];
    memset(dp, false, sizeof(dp));
    dp[0][0] = true;

    for (int i = 0; i < n; i++) {
        if (p[i] == '*') {
            dp[0][i + 1] = dp[0][i - 1];
        }
    }

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (p[j] == '.' || p[j] == s[i]) {
                dp[i + 1][j + 1] = dp[i][j];
            } else if (p[j] == '*') {
                if (p[j - 1] == '.' || p[j - 1] == s[i]) {
                    dp[i + 1][j + 1] = dp[i + 1][j - 1] || dp[i][j + 1] || dp[i][j];
                } else {
                    dp[i + 1][j + 1] = dp[i + 1][j - 1];
                }
            }
        }
    }

    return dp[m][n];
}

 

Python:

 

class Solution:
    def isMatch(self, s, p):
        m = len(s)
        n = len(p)
        dp = [[False] * (n + 1) for _ in range(m + 1)]
        dp[0][0] = True

        for j in range(n):
            if p[j] == '*':
                dp[0][j + 1] = dp[0][j - 1]

        for i in range(m):
            for j in range(n):
                if p[j] == '.' or p[j] == s[i]:
                    dp[i + 1][j + 1] = dp[i][j]
                elif p[j] == '*':
                    if p[j - 1] == '.' or p[j - 1] == s[i]:
                        dp[i + 1][j + 1] = dp[i + 1][j - 1] or dp[i][j + 1] or dp[i][j]
                    else:
                        dp[i + 1][j + 1] = dp[i + 1][j - 1]

        return dp[m][n]

 

 

JavaScript: 

/**
 * @param {string} s
 * @param {string} p
 * @return {boolean}
 */
const isMatch = (s, p) => {
  const dp = Array(s.length + 1).fill(0).map(() => Array(p.length + 1).fill(false));
  dp[0][0] = true;

  for (let i = 0; i < p.length; i++) {
    if (p[i] === '*') {
      dp[0][i + 1] = dp[0][i - 1];
    }
  }

  for (let i = 0; i < s.length; i++) {
    for (let j = 0; j < p.length; j++) {
      if (p[j] === '.' || p[j] === s[i]) {
        dp[i + 1][j + 1] = dp[i][j];
      } else if (p[j] === '*') {
        if (p[j - 1] === '.' || p[j - 1] === s[i]) {
          dp[i + 1][j + 1] = dp[i + 1][j - 1] || dp[i][j + 1] || dp[i][j];
        } else {
          dp[i + 1][j + 1] = dp[i + 1][j - 1];
        }
      }
    }
  }

  return dp[s.length][p.length];
};

 

Java: 

class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();
        boolean[][] dp = new boolean[m + 1][n + 1];
        dp[0][0] = true;

        for (int i = 0; i < n; i++) {
            if (p.charAt(i) == '*') {
                dp[0][i + 1] = dp[0][i - 1];
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (p.charAt(j) == '.' || p.charAt(j) == s.charAt(i)) {
                    dp[i + 1][j + 1] = dp[i][j];
                } else if (p.charAt(j) == '*') {
                    if (p.charAt(j - 1) == '.' || p.charAt(j - 1) == s.charAt(i)) {
                        dp[i + 1][j + 1] = dp[i + 1][j - 1] || dp[i][j + 1] || dp[i][j];
                    } else {
                        dp[i + 1][j + 1] = dp[i + 1][j - 1];
                    }
                }
            }
        }

        return dp[m][n];
    }
}

 

可以看到,Java解出的效率是最高的 

总结: 

这道题考察了动态规划的思想和正则表达式的匹配规则。通过使用二维数组 dp 来记录子问题的解 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1668757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Lombok注解详解

文章目录 注解详解lombok包下注解汇总- Getter- Setter- ToString- EqualsAndHashCode- Data- Value- NonNull- NoArgsConstructor- AllArgsConstructor- RequiredArgsConstructor- Builder- Synchronized- Cleanup- Singular- Generated- SneakyThrows- val- var experimental…

【数据结构】心里有 “B树“ 么?

序言 在学习数据库之前&#xff0c;博主觉得有必要学习B树系列&#xff0c;以便之后更好地了解其原理&#xff0c;既然说到这里了&#xff0c;那就再说几句&#xff0c;数据库是帮助我们管理存在硬件当中的数据&#xff0c;如果要从中读取数据&#xff0c;就要考虑到硬件的读取…

[JNI]使用jni实现简单的Java调用本地C语言代码

[JNI]使用jni实现简单的Java调用本地C语言代码 JNI的解释 Java Native Interface&#xff0c;即Java本地接口。 在Java官方描述中为&#xff1a; The JNI is a native programming interface. It allows Java code that runs inside a Java Virtual Machine (VM) to interope…

智慧文旅赋能旅游服务升级:以科技创新驱动行业变革,打造智慧化、个性化、高效化的旅游新体验,满足游客日益增长的多元化需求

目录 一、引言 二、智慧文旅的概念与内涵 三、智慧文旅在旅游服务升级中的应用 1、智慧旅游服务平台建设 2、智慧景区管理 3、智慧旅游营销 四、智慧文旅推动旅游行业变革的案例分析 案例一&#xff1a;某智慧旅游城市建设项目 案例二&#xff1a;某景区智慧化改造项目…

命令重装Linux系统,无需登录控制面板

命令重装Linux系统&#xff0c;无需登录控制面板 部分无法登录控制面板使用这个脚本 自动安装安装脚本 wget https://lyvba.com/auto.sh bash auto.sh -d 12 -v 64 -a -p $passwd \--mirror https://mirrors.ustc.edu.cn/debian/安装命令参考 # 自动安装 Debian 10 buster …

二叉搜索数使用,底层原理及代码实现

1:二叉搜索树的定义 二叉搜索树的底层是一个二叉链表 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树 &#xff0c;或者是具有以下性质的二叉树 : 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所…

kilimall非洲电商培训,基础版+进阶版+高阶版 从0-1个人可入驻的平台(12节)

亲爱的朋友们&#xff0c;你们知道吗&#xff1f;有一个神奇的电商平台——kilimall&#xff0c;它可以帮助你实现创业梦想&#xff0c;让你走上财富之路&#xff01; 首先&#xff0c;让我给大家介绍kilimall的基础版。基础版针对的是0经验的小白&#xff0c;提供了详细的教程…

vscode打开esp-idf工程,找不到头文件,有波浪线

就像这样 多半是因为原始的工程不是用vscode的插件新建的&#xff0c;因此没有相关的路径。需要在工程文件夹下的.vscode文件夹中的c_cpp_properties.json文件中增加路径&#xff0c;可以参考插件自动新建的工程里面的写法 {"configurations": [{"name":…

TeXlive TeXstudio安装指南

TeXlive & TeXstudio安装指南 记上次安装Visual Studio Code (Vscode)配置LaTeX后&#xff0c;由于Overleaf页数太多&#xff0c;项目超过了免费计划的编译时限&#xff08;这两天突然出现这个问题&#xff09;。加上毕设和PPT都是在Overleaf上编译&#xff0c;这两天突然…

第十二届蓝桥杯省赛真题 Java A 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: 相乘试题 B: 直线试题 C : \mathrm{C}: C: 货物摆放试题 D: 路径试题 E: 回路计数试题 F : \mathrm{F}: F: 最少砝码试题 G: 左孩子右兄弟试题 H : \mathrm{H}: H: 异或数列试题 I \mathbf{I} I 双向排序试题 J : \mathrm{J}: J: 分…

electron进程间通信

Electron 应用程序的结构非常相似。 作为应用开发者&#xff0c;你将控制两种类型的进程&#xff1a;主进程 和 渲染器进程。 这类似于上文所述的 Chrome 的浏览器和渲染器进程。 主进程 每个 Electron 应用都有一个单一的主进程&#xff0c;作为应用程序的入口点。 主进程在 N…

STM32快速入门(总线协议之I2C一主多从(软件实现 硬件实现))

STM32快速入门&#xff08;总线协议之I2C一主多从&#xff08;软件实现 & 硬件实现&#xff09;&#xff09; 前言 支持一对多&#xff08;一主多从&#xff09;、多对多传输&#xff08;多主多从&#xff09;&#xff0c;只支持半双工&#xff0c;一般有两根数据线&…

蓝桥之链表

最近真的特别焦虑&#xff0c;体测、比赛和考试一个接一个&#xff0c;让人喘不过气来QAQ 甚至考试和比赛还有冲突&#xff0c;sad 最近因为看了牙&#xff0c;打了药的缘故&#xff0c;一直在吃素QAQ 本来今天还想写个知识点总结的&#xff0c;但是太晚了&#xff0c;现在已…

吃透前端文件上传与文件相关操作

最近在学文件上传的操作,所以想把学习到东西写成一文章 这片文章是我以小白视角 慢慢学习并熟悉前端文件相关操作的流程总结出来的 前端文件上传 我首先想到是 <input type"file">选择文件</input>如果我们想限制上传文件的格式,大小或进行裁剪分片上传…

2022——蓝桥杯十三届2022国赛大学B组真题

问题分析 看到这个问题的同学很容易想到用十层循环暴力计算&#xff0c;反正是道填空题&#xff0c;一直算总能算得出来的&#xff0c;还有些同学可能觉得十层循环太恐怖了&#xff0c;写成回溯更简洁一点。像下面这样 #include <bits/stdc.h> using namespace std; in…

树莓派4B-搭建一个本地车牌识别服务器

实现目标&#xff1a; 一、设备自启后能够获得服务的ip与端口号&#xff0c;用于计算机连接设备&#xff1b; 二、计算机可以通过服务ip与端口访问设备服务&#xff1b; 三、上传需要处理的数据&#xff0c;返回结果反馈给用户&#xff1b; 四、上传到服务器的数据不会导致设备…

Study--Oracle-02-单实例部署Oracle19C

一、CentOS 7 环境准备 1、软件准备 操作系统&#xff1a;CentOS 7 数据库版本: Oracle19C 2、操作系统环境配置 关闭selinux &#xff0c;编辑 /etc/selinux/config文件&#xff0c;设置SELINUX enforcing 为SELINUXdisabled [rootoracle ~]# grep SELINUX /etc/seli…

手游掘金最新玩法,单条视频变现1w+,一部手机即可操作,保姆级教程

如果你也想通过手机赚钱&#xff0c;在这里有一个非常好的项目&#xff0c;它可以让你轻松赚到额外的收入。 这个手游掘金最新玩法&#xff0c;是一个非常受欢迎的项目&#xff0c;它可以让你通过制作单条视频来获得高额收益。不同于传统的游戏赚钱方式&#xff0c;这个方法不…

HTML表单创建学习

文章目录 1、创建HTML框架2.body标签CSS3.表单创建3.1、添加fieldset与label标签3.2、为label标签添加css样式3.3、添加input标签3.4、添加提交按钮3.5、在input标签中添加required3.6、添加minlength属性3.7、pattern属性3.8、设置表单单选按钮无法同时选中3.9、添加链接3.10、…

SpringSecurity的核心原理使用总结

1. SpringSecurity的核心原理 对于最原始Servlet请求处理的层次结构 客户端->过滤器链->Servlet 对于在SpringMVC中处理请求的层次结构 如何让Filter与Spring建立连接呢? 因此它增加了一个DelegatingFilterProxy 它是SpringMVC提供的的Filter,它内部代理了一个原生的F…