Arian Soleimanzadeh
  • 首页
  • 博客
  • 播客
  • 视频
  • 联系
العربيةArabic
DeutschGerman
EnglishEnglish
فارسیPersian
한국어Korean
中文Chinese
面板•快速联系

Languages

Choose your interface locale

ar

العربية

Arabic

de

Deutsch

German

en

English

English

fa

فارسی

Persian

ko

한국어

Korean

zh

中文

Chinese

预约咨询

发送一条简短消息——我会尽快回复。

LinkedIn快速回复
首页/文章/什么是 Regular Expression Matching?使用动态规划和 TypeScript 理解 Regex
Algorithms文章

什么是 Regular Expression Matching?使用动态规划和 TypeScript 理解 Regex

Regular Expression Matching 是经典动态规划问题,需要判断整个字符串能否匹配包含 . 和 * 的 Pattern。本文介绍状态定义、Star 处理、TypeScript 实现和复杂度。

2026年8月19日7 分钟阅读0 浏览
#Algorithms#Regex#Regular Expression#Dynamic Programming#String Algorithms#TypeScript

Arian Soleimanzadeh

Software Engineer & Researcher

使用动态规划表对包含 dot 和 star 的 Regular Expression Pattern 进行字符串匹配

Arian Soleimanzadeh

AI · 代码 · 产品

研究 + 工程
本页目录
DotStar为什么使用动态规划?DP 状态普通字符或 DotStarTypeScript 实现复杂度MemoizationRegex 与 Wildcard MatchingFull Match实际 Regex安全与性能技术面试重点常见错误总结

经典 Regular Expression Matching 问题中,Pattern 包含普通字符以及:

.  → 任意单个字符
*  → 前一个元素出现零次或多次

例如:

s = "aa"
p = "a*"

结果为 true。

Dot

. 可以匹配任意一个字符。

例如:

c.t

可以匹配 cat、cut 和 c9t。

Star

* 作用于前一个 Pattern Element。

a*

可以匹配空字符串、a、aa、aaa 等。

为什么使用动态规划?

Star 会产生多个选择:使用前一个元素零次、一次或多次。

这些选择会反复产生相同子问题,因此适合使用 Dynamic Programming 或 Memoization。

DP 状态

定义:

dp[i][j]

表示 String 前 i 个字符是否能够完整匹配 Pattern 前 j 个字符。

dp[0][0] = true

像 a*b*c* 这样的 Pattern 可以匹配空字符串。

普通字符或 Dot

如果当前字符相同,或者 Pattern 当前字符是 .:

dp[i][j] = dp[i - 1][j - 1]

Star

第一种情况是不使用前一个元素:

dp[i][j] = dp[i][j - 2]

如果前一个 Pattern 元素与当前 String 字符匹配,则 Star 可以继续 Consume:

dp[i][j] = dp[i][j] || dp[i - 1][j]

TypeScript 实现

function isRegexMatch(s: string, p: string): boolean {
  const dp = Array.from(
    { length: s.length + 1 },
    () => new Array(p.length + 1).fill(false)
  );

  dp[0][0] = true;

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

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

        if (
          p[j - 2] === '.' ||
          p[j - 2] === s[i - 1]
        ) {
          dp[i][j] =
            dp[i][j] || dp[i - 1][j];
        }
      }
    }
  }

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

复杂度

Time Complexity: O(n × m)
Space Complexity: O(n × m)

Memoization

递归解法中,当遇到 x* 时有两个主要选择:

跳过 x*

或者在当前字符匹配时:

Consume 一个字符并继续保留 x*

如果没有 Memoization,会重复计算大量相同状态。

Regex 与 Wildcard Matching

Regex 中:

. → 任意一个字符
* → 重复前一个元素

Wildcard 中通常是:

? → 任意一个字符
* → 任意字符序列

所以 * 的意义不同。

Full Match

这里要求 Pattern 匹配整个 String。

因此:

hello
ell

结果为 false,尽管 ell 是其中的 Substring。

实际 Regex

生产系统中的 Regex 通常用于:

  • Validation
  • Search
  • Log Filtering
  • Data Extraction
  • Text Processing

应用代码通常应该使用成熟的 Regex Engine,而不是自己实现完整 Regex 引擎。

安全与性能

一些 Backtracking Regex Engine 在特殊 Pattern 和输入组合下可能产生严重性能问题,这类风险常与 ReDoS 有关。

因此理解 Regex 的复杂度对生产系统同样重要。

技术面试重点

需要理解:

  • . 的意义。
  • * 依赖前一个元素。
  • DP State 定义。
  • Empty String 初始化。
  • Star 的零次和多次使用。
  • O(n × m) 复杂度。

常见错误

  • 把 * 当作独立通配符。
  • 认为 * 只能出现零次或一次。
  • 忘记 Empty String。
  • 把 Substring Match 当作 Full Match。

总结

Regular Expression Matching 是将递归 Branching 转换为 Dynamic Programming 的经典问题。

.  → 任意一个字符
x* → x 出现零次或多次

标准 DP 解法复杂度为:

Time: O(n × m)
Space: O(n × m)
本页目录
DotStar为什么使用动态规划?DP 状态普通字符或 DotStarTypeScript 实现复杂度MemoizationRegex 与 Wildcard MatchingFull Match实际 Regex安全与性能技术面试重点常见错误总结

文章信息

发布时间、阅读时长和浏览数据。

发布

2026年8月19日

更新

2026年8月19日

阅读时长

7 分钟阅读

浏览

0

作者

Arian Soleimanzadeh

上一篇

什么是 Rabin–Karp 算法?使用 Rolling Hash 进行字符串匹配

下一篇

B2B CRM 与 B2C CRM 有什么区别?从销售流程到软件架构

让我们构建清晰、快速而优雅的作品。

用于合作、咨询或产品工作的快速联系入口。

快速联系给我发邮件
Arian Soleimanzadeh

个人作品集,聚焦现代 Web 工程、UI 系统与实用型 AI 产品——干净的代码,清晰的设计。

快速链接

  • 关于
  • 博客
  • 项目
  • 联系

联系

  • info@ariansoleimanzadeh.site
  • soleimanzadeh.a.work@gmail.com

可联系时间: 工作日

通常回复时间在 24小时内。

订阅通讯

获取文章、项目与新版本发布的更新。

© 2026 ariansoleimanzadeh.site — 保留所有权利。

LinkedIn