LeetCode 10 — Regular Expression Matching

Undécimo y último problema de DP 2-D — Hard. Matchear regex con '.' (cualquier char) y '*' (0+ del previo). DP 2-D con casuística.

Enunciado

s es una cadena, p un patrón con caracteres normales, '.' y '*'. Devuelve True si p matchea toda s.


Solución — DP 2-D

class Solution:
    def isMatch(self, s, p):
        m, n = len(s), len(p)
        dp = [[False] * (n+1) for _ in range(m+1)]
        dp[0][0] = True
 
        # Patrón vacío matches s vacío. Patrones tipo a*, a*b*, etc. matchean s vacío
        for j in range(1, n+1):
            if p[j-1] == '*':
                dp[0][j] = dp[0][j-2]
 
        for i in range(1, m+1):
            for j in range(1, n+1):
                if p[j-1] == '.' or p[j-1] == s[i-1]:
                    dp[i][j] = dp[i-1][j-1]
                elif p[j-1] == '*':
                    dp[i][j] = dp[i][j-2]                            # 0 ocurrencias
                    if p[j-2] == '.' or p[j-2] == s[i-1]:
                        dp[i][j] |= dp[i-1][j]                       # ≥1 ocurrencia
 
        return dp[m][n]

Análisis: O(m·n).

Las 3 ramas

  • Match directo (char o .): heredar dp[i-1][j-1].
  • * con 0 ocurrencias: heredar dp[i][j-2] (saltar x*).
  • * con ≥1 ocurrencia: si p[j-2] matchea s[i-1], heredar dp[i-1][j] (consumir un char de s, mantener x*).

Cierre DP 2-D

#ProblemaIdea distintiva
162-unique-pathsCaminos en grid
21143-longest-common-subsequenceLCS clásico
3309-best-time-to-buy-and-sell-stock-with-cooldownState machine 3 estados
4518-coin-change-iiCombinaciones (moneda en bucle externo)
5494-target-sum0-1 knapsack con dict
697-interleaving-stringInterleave check con DP
772-edit-distanceLevenshtein clásico
8329-longest-increasing-path-in-a-matrixDFS + memo en grid
9115-distinct-subsequencesDP similar a LCS
10312-burst-balloonsInterval DP “al final”
11EsteRegex matching DP

Conexiones

Estado

  • Leído
  • Implementado desde cero
  • Resuelto en LeetCode
  • Patrón DP 2-D cerrado [OK]