前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试题噩梦之一——LeetCode题目10:正则表达式匹配

面试题噩梦之一——LeetCode题目10:正则表达式匹配

作者头像
二环宇少
发布2020-08-13 15:27:44
8340
发布2020-08-13 15:27:44
举报

原题描述

+

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符

'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖整个字符串s的,而不是部分字符串。

说明:

s 可能为空,且只包含从 a-z 的小写字母。

p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

示例 1

输入:s = "aa", p = "a"

输出:false

示例 2

输入:s = "aa", p = "a*"

输出:true

示例 3

输入:s = "ab", p = ".*"

输出:true

示例 4

输入:s = "aab", p = "c*a*b"

输出:true

示例 5

输入:s = "mississippi", p = "mis*is*p*."

输出:false

原题链接:https://leetcode-cn.com/problems/regular-expression-matching

进入问题

+

竟然有人直接在程序里面调用正则表达式的库?你这样面试绝对过不了的

言归正传,此题挺难,至少我提交代码之后对着bad case调了半天才调通。但这道题确实面试考过,所以我希望你至少在方法上有个印象,能吃透就更好了。

编译原理课程中讲过正则表达式的原理,可以转换为有限自动机问题,这是编程语言词法分析的必备工具。

但你应该注意的是,这道题目是一个非常简易的正则表达式匹配器,用自动机这个工具也不是不可以,但确实有大炮打蚊子的感觉,而且自动机的程序可不好写。而且面试的题,能在原理上复杂到哪去?

我觉得你应该想一想,p的子串和s的子串有没有联系?当然有!

最简单地情况,在不考虑'*'的时候,若p和s能够匹配,那么同时去掉p和s的首个字符之后的两个子串应该也是匹配的。如果考虑'*',这种类似的关系也存在,我们可以先分情况讨论一下这个规律。

思路解析

+

先借用python的一些表达:令 表示字符串 中以第 位开头的子串。

然后我们定义 :表示子串 与 是否匹配,那么 即为所求。

case 1

当 时,

case 2

当 时,

对于公式(2)需要做些解释:当 时,我们要关注它前面一个字符,即 。因为 在 中可以出现0次,也可以出现无数次,这分别对应两种情况。

出现0次的情况,意味着我们可以忽略 和 ,那么 。

出现1次或多次的情况,意味着字符串 也可能和 匹配,但前提是满足 。

到现在为止,你可以编写递归程序了。但题目这么明显的最优子结构也在提醒着你,这是一道练习动态规划的好题目,只不过你需要好好处理一些边界条件。

基本原理你已经知道了,但我还是希望你能够好好的动手写一写,对着bad case调一调加深理解。

复杂度分析

+

  • 时间复杂度:
  • 空间复杂度:

C++参考代码

+

为什么我要开辟(m+1)*(n+1)长度的数组?因为便于处理空串的情况。我假想每一个模式串和字符串最后一位都是\0,并且也参与匹配判断,那么当给定的p和s中有空串情况的时候,我也可以当做正常字符串去处理。

代码语言:javascript
复制
class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size();
        int n = p.size();
        bool head_match = false;
        vector<vector<bool>> dp(m+1, vector<bool>(n+1, true));
        
        for (int i = m; i >= 0; --i) {
            for (int j = n; j >= 0; --j) {

                if (i < m && j < n) head_match = s[i] == p[j] || p[j] == '.';
                else if (i == m && j == n) head_match = true;
                else head_match = false;
            
                if (j + 2 <= n && p[j+1] == '*') {
                    dp[i][j] = dp[i][j+2];
                    if (i + 1 <= m)
                        dp[i][j] = dp[i][j] || (dp[i+1][j] && head_match);
                } else {
                    dp[i][j] = head_match;
                    if (i + 1 <= m && j + 1 <= n)
                        dp[i][j] = dp[i][j] && dp[i+1][j+1];
                }
            }
        }

        return dp[0][0];
    }
};
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 互联网西门二少 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档