LeetCode算法 —— 正則表達式匹配(詳解官方動態規劃思想)

原本準備在暑假學習DP算法的,但最近感覺心裏少了什麼東西一樣,原來是自己不瞭解DP 導致的空落感,所以把官方的答案 和 度孃的解釋看了一遍,自己用 Debug 測試了一下,把自己的所想分享給大家 . . .
.
前文鏈接(遞歸解決正則表達式匹配):

LeetCode算法 —— 正則表達式匹配(詳解官方遞歸思想)


此文章主要講解 DP的運行過程 !!!

在這裏插入圖片描述

題目:
給你一個字符串 s 和一個字符規律 p,請你來實現一個支持 ‘.’ 和 ‘*’ 的正則表達式匹配。

‘.’ 匹配任意單個字符
‘*’ 匹配零個或多個前面的那一個元素

所謂匹配,是要涵蓋 整個 字符串 s的,而不是部分字符串。

說明:
s 可能爲空,且只包含從 a-z 的小寫字母。
p 可能爲空,且只包含從 a-z 的小寫字母,以及字符 . 和 *。

示例此處就不粘貼了

官方代碼如下:
在這裏插入圖片描述

官方用DP思想寫的代碼中,重要的地方我已經用紅色方框標明瞭起來,下來我們來討論一下他們的作用 . . .

官方思想解析:

在這裏插入圖片描述
在這裏插入圖片描述
.

上面的解析中畫紅色框的部分與上面代碼中畫框的部分相對應 . . .

切記程序中對數組下標的處理( + 1 ?)


.

下面我來帶大家走進 Debug的世界,看看這個 DP 是怎麼工作的 . . .

DP 過程解析

我們使用下面的數據進行測試(大家也可以試試別的數據):在這裏插入圖片描述1) 首先根據上面官方解析,我們準備一個容器,準備工作到位:

vector <vector<int> > vec(m + 1, vector<int>(n + 1));  
vec[0][0] = true;

此時的狀態圖如下所示:
在這裏插入圖片描述

我們的最終效果如下:
在這裏插入圖片描述

2) 遍歷容器裏的元素 vec[i][j](每個元素表示一個狀態,官方解析思想上面有):

for (size_t i = 0; i <= m; ++i)
{
    for (size_t j = 1; j <= n; ++j)    
    {
    
    }
}

這裏的 m是 s的大小,n是 p的大小 . . .

這裏的 i 是從 0 開始的,上面的截圖部分有誤,還請諒解 ^ _ ^

.

3)準備一個判斷對應字符是否相等的方法(這裏很佩服官方的作法,用的是 Lambda表達式):

auto JudgeIsNoMatch = [&s, &p](int i, int j) {
	if (i == 0) 			// 如果當前匹配s的長度爲 0,則直接返回
	    return false;
	
	if (p[j - 1] == '.') 		// . 可匹配萬物
	    return true;
	
	return s[i - 1] == p[j - 1];	// 判斷是否相等
};

.

4)當前p中的判斷字符是否爲 * 處理的部分:

// 等於 * 時處理的步驟
if (p[j - 1] == '*') {
    vec[i][j] |= vec[i][j - 2];		// 判斷是否可以捨棄 *號
    
    // j 與 i 前的所有字符匹配,保存記錄判斷到最後
    // 可以這個判斷有點萌幣,不急,看我下面的Debug 測試就知道了 )``^ _ ^``
    if (JudgeIsNoMatch(i, j - 1)) {	
    	vec[i][j] |= vec[i - 1][j];	// a* 要和 s中的 i - 1 個字符要匹配
    }
}

// 不等於 * 時處理的步驟
else {  
    //	直接判斷是否相等
    if (JudgeIsNoMatch(i, j)) {
    	// i - 1 個 s中的字符 要和 j - 1 個 p中的字符要相等
	vec[i][j] |= vec[i - 1][j - 1]; 	
    }
}

.

5)開始我們 Debug測試,看看我們的最終圖是如何求出解來的:
在這裏插入圖片描述

我們最終的結果就是判斷 vec[m][n] 是否爲 1 就行了,說明我們已經完美的匹配結束了 . . .
.
return vec[m][n];


.

Debug 測試結果

  1. 使用斷點,調試程序:
    在這裏插入圖片描述

.

  1. 當 i = 1,j = 1 時,執行 else 語句:
    在這裏插入圖片描述

    因爲 vec[0][0] = 1,所以 vec[1][1] |= vec[0][0] == 1;
    .
    此時,狀態圖如下:
    在這裏插入圖片描述

.

  1. 當 i = 2,j = 2 時,執行 else 語句:
    在這裏插入圖片描述

    原理與上面相同
    在這裏插入圖片描述

.

  1. 當 i = 2,j = 4 時,執行 if 中的語句:
    在這裏插入圖片描述

    此時,這句代碼將起到作用:
    vec[i][j] |= vec[i][j - 2];
    此處的 a* 將捨棄,這樣才能滿足題目的意思(所做的一切都是爲下面做服務) . . .
    在這裏插入圖片描述

  2. 當 i = 3,j = 3 時,與 2、3 是相同的:
    在這裏插入圖片描述

.

  1. 當 i = 3,j = 4時,執行下面的語句:
    在這裏插入圖片描述

    執行的代碼是:

    vec[i][j] |= vec[i - 1][j];

    因爲 if中判斷成功了,說明相應的字符是相同的,並且之間的字符也判斷相同了(vec[i - 1][j])證明 . . .在這裏插入圖片描述

.

  1. 當 i = 4, j = 4時,同 6 相同:
    在這裏插入圖片描述
    在這裏插入圖片描述

.

文章可能有許多寫的不好的地方,還請大家諒解,因爲我太困了 (>_<)

.

祝大家端午節安康←_←


浪子花夢

一個有趣的程序員 ~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章