[Leetcode] 10. Regular Expression Matching
[Leetcode] 10. Regular Expression Matching

[Leetcode] 10. Regular Expression Matching

์–ธ์–ด
Python
C
๋‚œ์ด๋„
Hard
๋‹ค์‹œ ํ’€์–ด๋ณด๊ธฐ
๋‹ค์‹œ ํ’€์–ด๋ณด๊ธฐ
์•Œ๊ณ ๋ฆฌ์ฆ˜ ์œ ํ˜•
๋™์  ๊ณ„ํš๋ฒ•
์žฌ๊ท€
์ž‘์„ฑ์ž
๋ฐ•์šฉ์„ฑ๋ฐ•์šฉ์„ฑ
์ƒ์„ฑ ์ผ์‹œ
2024๋…„ 10์›” 07์ผ

๐Ÿ–ฅ๏ธย ์‹œ์ž‘ํ•˜๋ฉฐ

1๏ธโƒฃย ๋ฌธ์ œ ์ ‘๊ทผ๋ฒ•

์ด ์ •๊ทœ ํ‘œํ˜„์‹ ๋งค์นญ ๋ฌธ์ œ๋Š” ์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด s์™€ ํŒจํ„ด p๊ฐ€ ์ฃผ์–ด์ง„ ๊ทœ์น™(.๊ณผ *)์— ๋”ฐ๋ผ ์ „์ฒด์ ์œผ๋กœ ์ผ์น˜ํ•˜๋Š”์ง€๋ฅผ ํŒ๋‹จํ•˜๋Š” ๋ฌธ์ œ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฌธ์ž์—ด๊ณผ ํŒจํ„ด์˜ ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„ ์กฐํ•ฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.
์ฒ˜์Œ์—๋Š” ๊ตฌํ˜„์œผ๋กœ ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์ง์ ‘ ๋””๋ฒ„๊น…ํ•˜๋ฉฐ ์ผ€์ด์Šค๋ฅผ ๋”ฐ์ ธ๋ณด๋‹ˆ ๋„ˆ๋ฌด ๋งŽ์€ ์ผ€์ด์Šค๊ฐ€ ๋‚˜์™€ ๊ตฌํ˜„๋ฒ•์ด ์žˆ๋‚˜ ์‹ถ์—ˆ๋‹ค. ์†”์งํžˆ ๋™์  ๊ณ„ํš๋ฒ•์ด๋ผ๊ณ  ๋– ์˜ฌ๋ฆฌ๊ธฐ ์‰ฝ์ง€ ์•Š์•˜๋‹ค. ์•„๋ž˜ ํŠน์ง•์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ์ˆ™์ง€ํ•˜์ž.

๐Ÿ’กย ๋™์  ๊ณ„ํš๋ฒ• ์ˆ™์ง€

  1. ๋ฌธ์ œ๋ฅผ ํ•˜์œ„ ๋ฌธ์ œ๋กœ ๋ถ„ํ• ํ•˜๊ธฐ
    1. ์–ด๋–ค ๋ฌธ์ œ๋ฅผ DP๋กœ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฌธ์ œ๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋” ์ž‘์€ ๋ฌธ์ œ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ด ๋ฌธ์ œ์˜ ๊ฒฝ์šฐ, ๋ฌธ์ž์—ด๊ณผ ํŒจํ„ด์˜ ๋ถ€๋ถ„ ๋ฌธ์ž์—ด์— ๋Œ€ํ•œ ์ผ์น˜ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•จ์œผ๋กœ์จ ๋ฌธ์ œ๋ฅผ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. ์ƒํƒœ ์ „์ด ์ดํ•ดํ•˜๊ธฐ
    1. ๊ฐ ์ƒํƒœ(dp[i][j])๊ฐ€ ์ด์ „ ์ƒํƒœ๋“ค๊ณผ ์–ด๋–ป๊ฒŒ ์—ฐ๊ฒฐ๋˜๋Š”์ง€๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค. ์ด๋Š” ์ ํ™”์‹์„ ์œ ๋„ํ•˜๋Š” ํ•ต์‹ฌ ๋‹จ๊ณ„๋‹ค.
  1. ์ค‘๋ณต ๊ณ„์‚ฐ ์ตœ์†Œํ™”
    1. DP์˜ ๋ชฉ์  ์ค‘ ํ•˜๋‚˜๋Š” ๋™์ผํ•œ ํ•˜์œ„ ๋ฌธ์ œ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ ๊ณ„์‚ฐํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•œ๋‹ค.
  1. ๋ฌธ์ œ์˜ ํŠน์ˆ˜ ์กฐ๊ฑด ์ฒ˜๋ฆฌ
    1. ํŠน์ˆ˜ ๋ฌธ์ž(.๊ณผ *)์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ , ์ด๋ฅผ ์ ํ™”์‹์— ๋ฐ˜์˜ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

2๏ธโƒฃย ์ ํ™”์‹, ๊ธฐ์ € ์กฐ๊ฑด ์„ค์ •

์ ํ™”์‹์€ DP์—์„œ ๊ฐ ์ƒํƒœ๊ฐ€ ์ด์ „ ์ƒํƒœ๋“ค๊ณผ ์–ด๋–ป๊ฒŒ ์—ฐ๊ด€๋˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ทœ์น™์œผ๋กœ ,๋™์  ๊ณ„ํš๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•ต์‹ฌ์ด๋‹ค.
  1. DP ํ…Œ์ด๋ธ” ์ •์˜
    1. dp[i][j]๋Š” ๋ฌธ์ž์—ด s์˜ ์ฒ˜์Œ i ๋ฌธ์ž(s[0..i-1])์™€ ํŒจํ„ด p์˜ ์ฒ˜์Œ j ๋ฌธ์ž(p[0..j-1])๊ฐ€ ์ผ์น˜ํ•˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
  1. ๊ธฐ๋ณธ ์‚ฌ๋ก€ ์„ค์ •
    1. ๋นˆ ๋ฌธ์ž์—ด๊ณผ ๋นˆ ํŒจํ„ด:
      1. dp[0][0] = True (๋นˆ ๋ฌธ์ž์—ด์€ ๋นˆ ํŒจํ„ด๊ณผ ์ผ์น˜ํ•˜๊ฒŒ ๋œ๋‹ค. ๊ธฐ์ € ์กฐ๊ฑด์„ ์„ค์ •ํ•œ๋‹ค.)
    2. ๋นˆ ๋ฌธ์ž์—ด๊ณผ ํŒจํ„ด:
      1. ํŒจํ„ด์ด * ๋ฅผ ํฌํ•จํ•˜์—ฌ ๋นˆ ๋ฌธ์ž์—ด๊ณผ ์ผ์น˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•œ๋‹ค. ํŒจํ„ด์ด "a*" ๋˜๋Š” "a*b*"์ธ ๊ฒฝ์šฐ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด dp[0][j]๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์ž.

3๏ธโƒฃย ์ ํ™”์‹ ์œ ๋„

๋ฌธ์ž์—ด s์™€ ํŒจํ„ด p์˜ ๊ฐ ๋ฌธ์ž๋ฅผ ๋น„๊ตํ•˜๋ฉด์„œ dp[i][j]๋ฅผ ์ฑ„์›Œ๋‚˜๊ฐ„๋‹ค.
์—ฌ๊ธฐ์„œ i๋Š” ๋ฌธ์ž์—ด s์˜ ์ธ๋ฑ์Šค, j๋Š” ํŒจํ„ด p์˜ ์ธ๋ฑ์Šค๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
  1. ์ง์ ‘ ์ผ์น˜ ๋˜๋Š” ์  ์—ฐ์‚ฐ์ž
      • ์กฐ๊ฑด: p[j-1] == s[i-1] ๋˜๋Š” p[j-1] == '.'
      • ์ด๋Š” ํ˜„์žฌ ํŒจํ„ด ๋ฌธ์ž๊ฐ€ ๋ฌธ์ž์—ด์˜ ํ˜„์žฌ ๋ฌธ์ž์™€ ์ผ์น˜ํ•˜๊ฑฐ๋‚˜, .์„ ์‚ฌ์šฉํ•˜์—ฌ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ๋‹ค.
      โ†’ dp[i][j] = dp[i-1][j-1] (์ง๊ด€์ ์œผ๋กœ ์ด์ „ ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค)
  1. ๋ณ„ํ‘œ ์—ฐ์‚ฐ์ž
      • ์กฐ๊ฑด: p[j-1] == '*'
      • ์ด๋Š” * ๊ฐ€ ๋ฐ”๋กœ ์•ž์˜ ๋ฌธ์ž๊ฐ€ 0ํšŒ ์ด์ƒ ๋ฐ˜๋ณต๋˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
      • * ๋Š” ๋‘ ๊ฐ€์ง€ ์ƒํ™ฉ์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ๋‹ค.
        • a. 0ํšŒ ๋ฐœ์ƒ (๋ฌธ์ž ์ œ๊ฑฐ):
        • * ์™€ ๊ทธ ์•ž์˜ ๋ฌธ์ž๋ฅผ ํŒจํ„ด์—์„œ ์ œ๊ฑฐํ•˜์—ฌ ํ˜„์žฌ ๋ฌธ์ž์—ด๊ณผ ํŒจํ„ด์˜ ์ด์ „ ์ƒํƒœ๋ฅผ ๋น„๊ต
        • โ†’ dp[i][j] = dp[i][j-2]
          b. 1ํšŒ ์ด์ƒ ๋ฐœ์ƒ (๋ฌธ์ž ๋ฐ˜๋ณต):
        • * ์•ž์˜ ๋ฌธ์ž๊ฐ€ ํ˜„์žฌ ๋ฌธ์ž์—ด์˜ ๋ฌธ์ž์™€ ์ผ์น˜ํ•˜๊ฑฐ๋‚˜, .์ธ ๊ฒฝ์šฐ
        • ์ด๋•Œ, ํŒจํ„ด์˜ * ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด์˜ ์ด์ „ ๋ฌธ์ž๊นŒ์ง€ ๋งค์นญ๋œ ์ƒํƒœ๋ฅผ ํ™•์ธ
        • โ†’ dp[i][j] = dp[i][j] or dp[i-1][j]
      ์ข…ํ•ฉํ•˜๋ฉด:
      if p[j-1] == '*': dp[i][j] = dp[i][j-2] if p[j-2] == s[i-1] or p[j-2] == '.': dp[i][j] = dp[i][j] or dp[i-1][j]

์ ํ™”์‹ ์š”์•ฝ

# DP ํ…Œ์ด๋ธ” ์ฑ„์šฐ๊ธฐ for i in range(1, len(s) + 1): for j in range(1, len(p) + 1): # ํ˜„์žฌ ๋ฌธ์ž๊ฐ€ ๋งค์น˜๋˜๋Š” ๊ฒฝ์šฐ (๊ฐ™์€ ๋ฌธ์ž์ด๊ฑฐ๋‚˜ '.'์ธ ๊ฒฝ์šฐ) if p[j - 1] == s[i - 1] or p[j - 1] == ".": # ํ˜„์žฌ ๋ฌธ์ž๊ฐ€ ๋งค์น˜๋˜๋ฉด, ์ด์ „ ์ƒํƒœ์˜ ๋งค์น˜ ์—ฌ๋ถ€๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ด # ์ฆ‰, ํ˜„์žฌ ๋ฌธ์ž๋ฅผ ์ œ์™ธํ•œ ์ด์ „๊นŒ์ง€์˜ ๋งค์น˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ dp[i][j] = dp[i - 1][j - 1] # ํ˜„์žฌ ํŒจํ„ด ๋ฌธ์ž๊ฐ€ '*'์ธ ๊ฒฝ์šฐ elif p[j - 1] == "*": # 1. '*' ์•ž์˜ ๋ฌธ์ž๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๊ฒฝ์šฐ (0๋ฒˆ ์‚ฌ์šฉ) # '*'์™€ ๊ทธ ์•ž์˜ ๋ฌธ์ž๋ฅผ ๋ชจ๋‘ ๋ฌด์‹œํ•˜๊ณ , ๊ทธ ์ด์ „ ์ƒํƒœ์˜ ๋งค์น˜ ์—ฌ๋ถ€๋ฅผ ๊ฐ€์ ธ์˜ด dp[i][j] = dp[i][j - 2] # 2. '*' ์•ž์˜ ๋ฌธ์ž๊ฐ€ ํ˜„์žฌ ๋ฌธ์ž์™€ ๋งค์น˜๋˜๊ฑฐ๋‚˜ '.'์ธ ๊ฒฝ์šฐ if p[j - 2] == s[i - 1] or p[j - 2] == ".": # '*' ์•ž์˜ ๋ฌธ์ž๋ฅผ ํ•œ ๋ฒˆ ์ด์ƒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ # ํ˜„์žฌ ๋ฌธ์ž๋ฅผ ๋งค์น˜์‹œํ‚ค๊ณ , ์ด์ „ ๋ฌธ์ž์—ด ์ƒํƒœ์˜ ๋งค์น˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ # 'or' ์—ฐ์‚ฐ์€ ์ด์ „ ๋‹จ๊ณ„(dp[i][j - 2])์™€ ํ˜„์žฌ ๋‹จ๊ณ„ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ฐธ์ด๋ฉด ์ฐธ dp[i][j] = dp[i][j] or dp[i - 1][j]
๐Ÿ’กย ์ ํ™”์‹์˜ ์ง๊ด€์  ์ดํ•ด

4๏ธโƒฃย ์˜ˆ์ œ๋ฅผ ํ†ตํ•œ ์ ํ™”์‹ ์ ์šฉ ์ดํ•ด

์˜ˆ์ œ:

  • ์ž…๋ ฅ: s = "aab", p = "c*a*b"
  • ๋ชฉํ‘œ: dp[3][5]์˜ ๊ฐ’์„ ๊ตฌํ•˜๋Š” ๊ฒƒ

๋‹จ๊ณ„๋ณ„ ๊ณผ์ •:

  1. ์ดˆ๊ธฐํ™”:
      • dp[0][0] = True
      • dp[0][2] = True ("c*"๋Š” 0ํšŒ ๋ฐœ์ƒ)
      • dp[0][4] = True ("c*a*"๋Š” 0ํšŒ ๋ฐœ์ƒ)
  1. DP ํ…Œ์ด๋ธ” ์ฑ„์šฐ๊ธฐ:
    1. ใ…ค
      ๋นˆ ๋ฌธ์ž
      c
      *
      a
      *
      b
      ๋นˆ ๋ฌธ์ž
      T
      F
      T
      F
      T
      F
      a
      F
      F
      F
      T
      T
      F
      a
      F
      F
      F
      F
      T
      F
      b
      F
      F
      F
      F
      F
      T
      • ๊ฐ dp[i][j]๋Š” ์ด์ „ ์ƒํƒœ๋“ค์„ ์ฐธ์กฐํ•˜์—ฌ ์ฑ„์›Œ์ง„๋‹ค.
      • ์˜ˆ๋ฅผ ๋“ค์–ด dp[1][3] ("a" vs "c*a")๋Š” dp[0][2] ("" vs "c*")์„ ์ฐธ์กฐํ•˜์—ฌ True๊ฐ€ ๋œ๋‹ค.
ย 

โš™๏ธย Python

from typing import List from itertools import zip_longest class Solution: def isMatch(self, s: str, p: str) -> bool: # DP ํ…Œ์ด๋ธ” ์ดˆ๊ธฐํ™” dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)] # ๋นˆ ๋ฌธ์ž์—ด๊ณผ ๋นˆ ํŒจํ„ด์€ ๋งค์น˜๋จ dp[0][0] = True # ํŒจํ„ด์ด '*'๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ # ์ด ๊ฒฝ์šฐ ๋นˆ ํŒจํ„ด๊ณผ ๋งค์น˜๋  ์ˆ˜ ์žˆ์Œ for j in range(1, len(p) + 1): if p[j - 1] == "*": dp[0][j] = dp[0][j - 2] # DP ํ…Œ์ด๋ธ” ์ฑ„์šฐ๊ธฐ for i in range(1, len(s) + 1): for j in range(1, len(p) + 1): # ํ˜„์žฌ ๋ฌธ์ž๊ฐ€ ๋งค์น˜๋˜๋Š” ๊ฒฝ์šฐ (๊ฐ™์€ ๋ฌธ์ž์ด๊ฑฐ๋‚˜ '.'์ธ ๊ฒฝ์šฐ) if p[j - 1] == s[i - 1] or p[j - 1] == ".": # ํ˜„์žฌ ๋ฌธ์ž๊ฐ€ ๋งค์น˜๋˜๋ฉด, ์ด์ „ ์ƒํƒœ์˜ ๋งค์น˜ ์—ฌ๋ถ€๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ด # ์ฆ‰, ํ˜„์žฌ ๋ฌธ์ž๋ฅผ ์ œ์™ธํ•œ ์ด์ „๊นŒ์ง€์˜ ๋งค์น˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ dp[i][j] = dp[i - 1][j - 1] # ํ˜„์žฌ ํŒจํ„ด ๋ฌธ์ž๊ฐ€ '*'์ธ ๊ฒฝ์šฐ elif p[j - 1] == "*": # 1. '*' ์•ž์˜ ๋ฌธ์ž๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๊ฒฝ์šฐ (0๋ฒˆ ์‚ฌ์šฉ) # '*'์™€ ๊ทธ ์•ž์˜ ๋ฌธ์ž๋ฅผ ๋ชจ๋‘ ๋ฌด์‹œํ•˜๊ณ , ๊ทธ ์ด์ „ ์ƒํƒœ์˜ ๋งค์น˜ ์—ฌ๋ถ€๋ฅผ ๊ฐ€์ ธ์˜ด dp[i][j] = dp[i][j - 2] # 2. '*' ์•ž์˜ ๋ฌธ์ž๊ฐ€ ํ˜„์žฌ ๋ฌธ์ž์™€ ๋งค์น˜๋˜๊ฑฐ๋‚˜ '.'์ธ ๊ฒฝ์šฐ if p[j - 2] == s[i - 1] or p[j - 2] == ".": # '*' ์•ž์˜ ๋ฌธ์ž๋ฅผ ํ•œ ๋ฒˆ ์ด์ƒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ # ํ˜„์žฌ ๋ฌธ์ž๋ฅผ ๋งค์น˜์‹œํ‚ค๊ณ , ์ด์ „ ๋ฌธ์ž์—ด ์ƒํƒœ์˜ ๋งค์น˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ # 'or' ์—ฐ์‚ฐ์€ ์ด์ „ ๋‹จ๊ณ„(dp[i][j - 2])์™€ ํ˜„์žฌ ๋‹จ๊ณ„ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ฐธ์ด๋ฉด ์ฐธ dp[i][j] = dp[i][j] or dp[i - 1][j] # ์ตœ์ข… ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ return dp[len(s)][len(p)] if __name__ == "__main__": sol = Solution() print(sol.isMatch("aab", "c*a*b"))
ย 

๐Ÿ“Œย ์†Œ๊ฐ

์™€.. ์ง„์งœ ์˜ค๋žœ๋งŒ์— DP ๋ฌธ์ œ ํ’€์—ˆ๋Š”๋ฐ ๋„ˆ๋ฌด ์–ด๋ ต๋‹ค. ๋งํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

๋Œ“๊ธ€

guest