leetCode题之正则表达匹配

本文介绍了一种使用动态规划解决正则表达式匹配问题的算法,通过详细的代码示例和测试案例,展示了如何实现正则表达式的完全匹配,特别关注了‘.’和‘*’字符的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题

Given an input string (s) and a pattern §, implement regular expression matching with support for ‘.’ and ‘’.
‘.’ Matches any single character.
'
’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.

即给定字符串s(全部小写), 一个正则表达式p(仅包含’.‘和’*'符号, 字母小写). 输出字符串是否完全匹配.

先写测试代码

import unittest
from main import Solution

class TestMain(unittest.TestCase):
    def setUp(self):
        self.solver = Solution()
        self.cases = [
            {
                "feed": 'abcdefggghi',
                "regexp": 'a..defg*hi',
                "want": True
            },
            {
                "feed": 'some text',
                "regexp": '.*text',
                "want": True
            },
            {
                "feed": 'abcddddffg',
                "regexp": 'n*ab.*g',
                "want": True
            },
            {
                "feed": 'abcddddffg',
                "regexp": 'n.ab.*g',
                "want": False
            },
            {
                "feed": '',
                "regexp": 'n.ab.*g',
                "want": False
            },
            {
                "feed": 'abcdef',
                "regexp": 'abcdefgh',
                "want": False
            },
            {
                "feed": 'aab',
                "regexp": 'c*a*b',
                "want": True
            },
        ]

    def testCase(self):
        for case in self.cases:
            res = self.solver.isMatch(case["feed"], case["regexp"])
            self.assertEqual(res, case["want"], "feed:{}, exp:{}".format(case["feed"], case["regexp"]))

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(TestMain)
    unittest.TextTestRunner(verbosity=2).run(suite)

解法

一般是采用动态规划法, 假设s长度为m, p长度为n, 设置一个dp[m+1][n+1]数组保存判断各种情况的结果。

  • 如果 p[j] == ‘*’ 则 dp[i][j]为True的情况为:
  1. dp[i][j-1] == True; 如 s=‘abcd’, p=‘a.*cd’, i=1, j=2;
  2. dp[i-1][j] 且( s[i-1] == p[j-1] or p[j-1] ==’.’)
  • 如果p[j] != ‘*’ 则dp[i][j]为True的情况为:
    dp[i-1][j] and (s[i-1] == p[j] or p[j] == ‘.’)

实际时,将dp[0][0]表示为s=’’, p=’'的情况; 完整代码如下:

class Solution(object):
    def isMatch(self, s, p):
        m = len(s)
        n = len(p)
        dp = [[False] * (n+1) for _ in range(m+1)]
        dp[0][0] = True
        for i in range(0, m+1):
            for j in range(1, n+1):
                if p[j-1] == '*':
                    dp[i][j] = dp[i][j-2] or ( i>0 and (s[i-1] == p[j-2] or p[j-2] == '.') and dp[i-1][j])
                else:
                    dp[i][j] = i>0 and dp[i-1][j-1] and (s[i-1] == p[j-1] or p[j-1] == '.')
        return dp[m][n]

运行

> python3 test.py
testCase (__main__.TestMain) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值