Leetcode 题解系列(六)

10. Regular Expression Matching

题目要求

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).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
题目分析
1. 使用递归

对于串s和模式p,有:
1. 如果p[1]是常规字符,那么在p[0]等于s[0] 或者 p[0]是通配符.的时候,问题等价与子串s[1: ]和子模式p[1: ]匹配。
2. 如果p[1]是字符*,问题分为两类,一是s[0]继续匹配到p[0],那么问题等价于串s[1: ]与模式p匹配;二是s[0]不匹配到p[0],那么问题等价于串s匹配p[2: ]
写成代码有:

class Solution {
 public:
  bool isMatch(string s, string p) {
    return isMatchImpl(s.c_str(), s.size(), p.c_str(), p.size());
  }
  bool isMatchImpl(const char* s, size_t s_len, const char* p, size_t p_len) {
    if (p_len == 0) return s_len == 0;
    bool head = s_len != 0 && (p[0] == s[0] || *p == '.');
    if (p_len >= 2 && *(p + 1) == '*') {
      return isMatchImpl(s, s_len, p + 2, p_len - 2) ||
             (head && isMatchImpl(s + 1, s_len - 1, p, p_len));
    } else {
      return head && isMatchImpl(s + 1, s_len - 1, p + 1, p_len - 1);
    }
  }
};
2. 保存中间状态

在上述解法中,如果大量出现重复匹配模式*,那么在递归的时候会重复计算部分子串与子模式的匹配问题。为了减少无效的重复计算,可以使用一个二维数组保存状态,提高性能。

class Solution {
  char** store;
  int slen, plen;
  bool isMatch(string s, string p) {
    slen = s.size(), plen = p.size();
    store = new char*[slen + 1]();
    for (int i = 0; i <= slen; ++i) {
      store[i] = new char[plen + 1]();
    }
    bool result = isMatchImpl2(0, 0, s.c_str(), p.c_str());
    for (int i = 0; i <= slen; ++i) {
      delete[] store[i];
    }
    delete[] store;
    return result;
  }

  bool isMatchImpl(int i, int j, const char* s, const char* p) {
    if (store[i][j] != 0) {
      return store[i][j] == 2;
    }
    bool result;
    if (j == plen) {
      result = i == slen;
    } else {
      bool head = i < slen && (p[j] == s[i] || p[j] == '.');

      if (j + 1 < plen && p[j + 1] == '*') {
        result = isMatchImpl(i, j + 2, s, p) ||
              (head && isMatchImpl(i + 1, j, s, p));
      } else {
        result = head && isMatchImpl(i + 1, j + 1, s, p);
      }
    }
    store[i][j] = result ? 2 : 1;
    return result;
  }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值