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

LeetCode 10:正则表达式匹配

LeetCode 10:正则表达式匹配

在这里插入图片描述

问题本质:精准匹配规则

实现支持 .(匹配任意单个字符)和 *(匹配前一个字符0次或多次)的正则表达式,要求完全匹配字符串 s,而非部分匹配。

核心思路:动态规划(DP)

通过二维 DP 表记录状态:dp[i][j] 表示 s 的前 i 个字符p 的前 j 个字符是否匹配。

算法步骤详解

步骤 1:状态定义

创建二维数组 dp,维度为 (m+1) × (n+1)m = s.length()n = p.length()):

  • dp[i][j]s 的前 i 个字符(s[0..i-1])与 p 的前 j 个字符(p[0..j-1])是否匹配。
步骤 2:初始化边界
  • 空字符串匹配dp[0][0] = true(空 s 匹配空 p)。
  • 处理 p 前导的 *:若 pa*b* 形式开头,空 s 也可匹配。例如:
    • p[j-1] == '*' 时,dp[0][j] = dp[0][j-2](忽略 p[j-2]p[j-1],即 * 匹配0次前一个字符)。
步骤 3:状态转移(核心逻辑)

遍历 is 的前 i 个字符)和 jp 的前 j 个字符),分两种情况:

情况 1:p[j-1] ≠ '*'(普通字符或 .
  • s[i-1]p[j-1] 匹配(s[i-1] == p[j-1]p[j-1] == '.'),且 s 的前 i-1 个字符与 p 的前 j-1 个字符匹配dp[i-1][j-1] == true),则 dp[i][j] = true
情况 2:p[j-1] == '*'(匹配前一个字符0次或多次)

* 修饰 p[j-2],分两种子情况:

  • 子情况 1:* 匹配0次:忽略 p[j-2]p[j-1],则 dp[i][j] = dp[i][j-2]
  • 子情况 2:* 匹配至少1次:需满足:
    1. s[i-1]p[j-2] 匹配(s[i-1] == p[j-2]p[j-2] == '.');
    2. s 的前 i-1 个字符与 p 的前 j 个字符匹配dp[i-1][j] == true,因为 * 可延续匹配)。
      此时 dp[i][j] |= dp[i-1][j](“或”操作,继承子情况1的结果)。

完整代码(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; // 空字符串匹配空正则// 初始化:处理p中前导的*(空s匹配p的情况)for (int j = 2; j <= n; j++) {if (p.charAt(j - 1) == '*') {dp[0][j] = dp[0][j - 2];}}// 填充DP表for (int i = 0; i <= m; i++) {for (int j = 1; j <= n; j++) {if (p.charAt(j - 1) != '*') {// 情况1:普通字符或.,需i>0且当前字符匹配,且前i-1和j-1匹配if (i > 0 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.')) {dp[i][j] = dp[i - 1][j - 1];}} else {// 情况2:*,分匹配0次和至少1次// 子情况1:匹配0次,直接继承j-2的状态dp[i][j] = dp[i][j - 2];// 子情况2:匹配至少1次,需i>0且当前字符匹配,继承i-1的状态if (i > 0 && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.')) {dp[i][j] |= dp[i - 1][j];}}}}return dp[m][n];}
}

关键细节解析

  1. 索引处理s[i-1]p[j-1] 对应字符串的第 ij 个字符(数组从0开始)。
  2. * 的灵活性:通过“匹配0次”和“匹配至少1次”的逻辑,覆盖所有可能的重复情况。
  3. 初始化优化:提前处理 p 中前导 * 的情况,确保空字符串的匹配性。

复杂度分析

  • 时间复杂度O(m×n)mn 分别是 sp 的长度,双重循环遍历所有状态。
  • 空间复杂度O(m×n),存储二维 DP 表。

示例验证

  • 示例 2s="aa", p="a*"):
    • dp[2][2]p[1]='*',匹配0次时 dp[2][0]=false;匹配至少1次时,s[1]='a' == p[0]='a',且 dp[1][2]=truei=1 时已匹配),故 dp[2][2]=true
  • 示例 3s="ab", p=".*"):
    • p[1]='*' 修饰 .,匹配0次时 dp[2][0]=false;匹配至少1次时,s[1]='b'. 匹配,且 dp[1][2]=truei=1s[0]='a' 匹配 .),故 dp[2][2]=true

该方案通过动态规划精准建模匹配状态,高效处理 * 的复杂逻辑,确保了正则表达式匹配的正确性与性能。

http://www.lryc.cn/news/598252.html

相关文章:

  • Python:开启机器学习的魔法之门
  • 无源域自适应综合研究【2】
  • Android Telephony UrspRule 介绍
  • EVAL长度限制突破方法
  • C#_定时器_解析
  • Flink-1.19.0源码详解7-Flink集群端调度
  • ubuntu安装teams解决方法
  • 大模型回复数据标注优化方案
  • 系统架构师:系统安全与分析-思维导图
  • AIRIOT智慧选煤厂管理解决方案
  • 家政小程序系统开发:开启智慧家政新时代
  • Nginx 信创版本源码升级 1.22.1 升级到1.28.0
  • SSE与Websocket有什么区别?
  • uniapp nvue开发App 横竖屏切换丢失上下文导致 setTimeout和clearTimeout报错
  • 全面解析 CSS Flex 布局:从入门到精通的所有属性详解
  • 深入掌握CSS Grid布局:每个属性详解与实战示例
  • k8s通过NUMA亲和分配GPU和VF接口
  • DeepSeek-R1+豆包迭代一次完成中国象棋游戏
  • 二、计算机网络技术——第6章:应用层
  • rk3588开发板使用硬件编码处理视频
  • 国产数据库拐点已至:电科金仓用“融合+AI”重新定义下一代数据底座
  • C++ 23种设计模式-工厂模式
  • (实用攻略)Linux操作系统(一)
  • 输电线路微气象在线监测装置:保障电网安全的科技屏障
  • 【基础】go基础学习笔记
  • 进阶向:基于Python的本地文件内容搜索工具
  • SpringCloud【Sentinel】
  • 【C++】类和对象(1)
  • CDH yarn 重启后RM两个备
  • Compose 适配 - 键鼠模式