Leetcode個人題解10

LEETCODE專題


10. Regular Expression Matching


  首先我們先來看一下題目要求:
  這裏寫圖片描述


  這裏先要講講題目的要求。
  這裏題目要求需要來個分類討論,一個大類是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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章