📝

Leetcode 10

Importance
📙📙📙
Start Date
Apr 8, 2025 15:39
tags
Dynamic Programming
Link:

题目要求

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
  • '.' 匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串。
 

核心算法和原理

  • 子序列问题容易想到dp
  • dp数组定义:dp[i][j] 表示 s[..i - 1] 与 p [..j - 1]是否匹配,i = 0或j = 0表示匹配无字符的情况
  • 状态转移:分j == ‘*’, ‘.’和普通字符的情况
    • 普通字符 / ‘.’:相等则dp[i][j] = dp[i - 1][j - 1]
    • ‘*’:根据匹配个数不同来确定:
      • 匹配0个:dp[i][j - 2]
      • 匹配一个或多个:如果s[i - 1] == p[j - 2] || p[j - 2] == ‘.’(也就是星号前面那个)则dp[i - 1][j]
    • 其他情况都为false
  • 初始化:dp[0][0] = true,同时注意如果p的开头存在匹配0个字符的情况则dp[0][j] = true
    • e.g. a*c*b
  • 拓展:如果还有’?’ (匹配0或1个),则和*类似,不匹配多个即 = dp[i][j - 2] || dp[i][j - 1]
 

代码

class Solution { public: bool isMatch(string s, string p) { int m = s.size(), n = p.size(); vector dp(m + 1, vector<bool>(n + 1, false)); dp[0][0] = true; for (int j = 2; j <= n && p[j - 1] == '*'; j += 2) { dp[0][j] = true; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (p[j - 1] == s[i - 1] || p[j - 1] == '.') { dp[i][j] = dp[i - 1][j - 1]; } else if (p[j - 1] == '*') { dp[i][j] = dp[i][j - 2] || (dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.')); } } } return dp[m][n]; } };