Leetcode个人题解10

LEETCODE专题


10. Regular Expression Matching


  首先我們先來看一下題目要求:
  Leetcode个人题解10_第1张图片


  这里先要讲讲题目的要求。
  这里题目要求需要来个分类讨论,一个大类是p中’‘字符, 另一个大类是p中的非’‘字符。这里需要进行一个条件判断。这也是这道题的一个大坑。
  如果单单从条件判断来进行,就要考虑很多种情况,测试的输入比样例的输入要复杂得多,多样得多。譬如s=”aaa”, p=”a*ab*c*”; s=”aacccbbaabb”, p=”.aabb”。这样就要考虑非’‘字符优先匹配。刚开始笔者陷入这个坑中的时候甚至还想过开两个队列来存储非’‘字符和’‘,以便分开匹配。但是这一条路走到黑,也的确就是黑了。
  后来学了动态规划之后发现其实这个问题是有最优子结构的,也就是说两个字符串的前缀就是这个问题的子问题。
  参照背包问题的动态规划解法,我们可以新建一个二维数组,如m[x][y]来记录两个字串的匹配与否。例如,m[0][0]表示取s的0个字符,p的0个字符来进行匹配,匹配结果为true;m[2][3]表示取s的2个字符,p的3个字符进行匹配。

接下来就是分类的处理:

  1. 不带’*’的字符匹配:直接匹配当前的s字符和p字符
  2. 带’*’的字符匹配:若s当前字符与p的上一个字符不匹配,则两个字符串仍然能够匹配的可能就是p的带’*’字符和p的上一个字符的组成字符串匹配数为0;如果s当前字符与p的上一个字符匹配,则两个字符串能够匹配的可能就是s的上一个字符和p的带’*’字符及上一个字符的组成字符串匹配,或者我们可以选择不匹配。

    这里注意下,能够匹配并不仅仅意味着两个字符一模一样,也有可能p的当前字符为’.’,能够匹配任何字符。


下面直接上代码:

class Solution {
public:
    bool isMatch(string s, string p) {
        /**
         * This problem is a typical knapsack
         * of prefix, we can then set the 2-D
         * bool matrix for matched.
         * m[i][j] stands for 
         * s[0, 1..i - 1]
         * is matched with
         * p[0, 1..j - 1]
         *
         * Also, there are 2 situations we can
         * tell if they are matched;
         * 1. p[j - 1] != '*', then
         * (m[i - 1][j - 1] &&
         * (s[i - 1] == p[j - 1] ||
         * p[j - 1] == '.') ) must be TRUE
         * OR
         * 2. p[j - 1] == '*', then
         * a.if p[j - 2] cannot be matched,
         * m[i][j - 2] must be TRUE
         * OR
         * b.if p[j - 2] can be matched
         * (p[j - 2] can be '.'), then
         * (s[i - 1] == p[j - 2] ||
         * p[j - 2] == '.') &&
         * m[i - 1][j] must be TRUE
        **/

        // firstly, check if both of them are empty
        if (s.empty() && p.empty()) return true;
        else if (p.empty()) return false;

        int iend = s.size() + 1;
        int jend = p.size() + 1;
        int i, j;
        vector<vector<bool> > m(iend, vector<bool>(jend, false));

        m[0][0] = true;
        for (j = 1; j < jend; j++) {
            m[0][j] = (j > 1 && p[j - 1] == '*' && m[0][j - 2]);
        }
        for (i = 1; i < iend; i++) {
            m[i][0] = false;
        }

        // matching begins
        for (i = 1; i < iend; i++) {
            for (j = 1; j < jend; j++) {
                if (p[j - 1] != '*') {
                    m[i][j] = m[i - 1][j - 1] &&
                        (s[i - 1] == p[j - 1] || p[j - 1] == '.');
                } else if (j > 1) {
                    if (p[j - 2] != s[i - 1] && p[j - 2] != '.') {
                        m[i][j] = m[i][j - 2];
                    } else {
                        m[i][j] = (m[i - 1][j] || m[i][j - 2]);
                    }
                } else {
                    m[i][j] = false;
                }
            }
        }

        return m[iend - 1][jend - 1];
    }
};
时间复杂度:O(n^2)

你可能感兴趣的:(算法c++,leetcode,c++)