剑指offer 正则表达式匹配(dp)

题目链接:正则表达式匹配

题目描述

请实现一个函数用来匹配包括'.''*'的正则表达式。

模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。

在本题中,匹配是指字符串的所有字符匹配整个模式。

例如,字符串"aaa"与模式"a.a""ab*ac*a"匹配,但是与"aa.a""ab*a"均不匹配。

思路

剑指offer里面用了层层指针做的。其实本质上就是一个 dp。

我们假设给定的主传是 s ,匹配串是 p.

定义:f[i][j]表示 p 从 j 开始到结尾,能否匹配 s 从 i 开始到结尾。

那么状态转移为:

  1. 如果 p[j+1] 不是通配符 * ,则 f[i][j] 是真,当且仅当 s[i] 可以和 p[j] 匹配,且 f[i+1][j+1] 是真。
  2. 如果 p[j+1] 是通配符 * ,则下面的情况只要有一种满足,f[i][j] 就是真:
    • f[i][j+2] 是真
    • s[i] 可以和 p[j] 匹配,且 f[i+1][j] 是真。(比如 s 串是 aaaaa , p 串是 a*a)

时间复杂度是: n n n 表示 s s s 的长度, m m m 表示 p p p 的长度,一共有 n m nm nm 个状态,总的时间复杂度是 O ( n m ) O(nm) O(nm)

代码

指针版

class Solution
{
  public:
    bool match(char *str, char *pattern)
    {
        if (str == NULL || pattern == NULL)
            return false;
        return dp(str, pattern);
    }
    bool dp(char *s, char *p)
    {
        if (*s == '\0' && *p == '\0')
            return true;
        if (*s != '\0' && *p == '\0')
            return false;
        if (*(p + 1) == '*')
        {
            if (*p == *s || (*p == '.' && *s != '\0'))
                return dp(s + 1, p + 2) || dp(s + 1, p) || dp(s, p + 2);
            else
                return dp(s, p + 2);
        }
        if (*s == *p || (*p == '.' && *s != '\0'))
            return dp(s + 1, p + 1);
        return false;
    }
};

vector 数组版:

class Solution
{
  public:
    vector<vector<int>> f;
    int n, m;
    bool isMatch(string s, string p)
    {
        n = s.size(), m = p.size();
        f = vector<vector<int>>(n + 1, vector<int>(m + 1, -1));
        return dp(0, 0, s, p);
    }
    bool dp(int x, int y, string &s, string &p)
    {
        if (~f[x][y])
            return f[x][y];
        if (y == m)
            return f[x][y] = (x == n);
        bool first_match = x < n && (s[x] == p[y] || p[y] == '.');
        bool ans;
        if (y + 1 < m && p[y + 1] == '*')
            ans = dp(x, y + 2, s, p) || (first_match && dp(x + 1, y, s, p));
        else
            ans = first_match && dp(x + 1, y + 1, s, p);
        return f[x][y] = ans;
    }
};
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值