Leetcode:正則表達式匹配

目錄

普通版本(動態規劃)

狀態表示

狀態轉移方程

優化③①情況

數學化簡分析

結合實際情況畫圖化簡分析

總結

最終代碼


題目鏈接:10. 正則表達式匹配 - 力扣(LeetCode)

好像是leetcode前100道里面最難的一道?我是fw🤡

普通版本(動態規劃)

題目條件:

  • '.'?匹配任意單個字符
  • '*'?匹配零個或多個前面的那一個元素(將其理解為*號,某字符*表示可以有n個該字符)
  • 每次出現字符?*?時,前面都匹配到有效的字符(只有a~z*、.*兩種情況)

注意事項:字符*,變化的多出來的字符是向后延申的

條件解析與示例分析:

示例1:s = "aa"、p = "a",可匹配

示例2:s = "aa"、p = "a*",a*是一個整體,可以表示0~n個a,可匹配

示例3:s = "ab"、p = ".*",.*是一個整體,可以表示0~n個.,每個.可代表任意字符,可匹配

示例4:s = "aab"、p = "d*a*b",將d*視為一個空串,a*表示兩個a,b不變,可匹配

狀態表示

分析:由題意得我們可以要判斷的是p中[0,j]范圍內的字符是否能匹配s中[0,i]范圍內的字符,涉及了兩個數組間情況得判斷

結論:狀態轉移方程為dp[i][j],該方程表示p[0,j]范圍內的子串是否可以匹配s[0,j]范圍內的子串?

狀態轉移方程

主旨:根據p數組最后位置的取值進行分情況討論(s[i]和p[j]分別表示s和p數組最后位置的字符)

①p[j]是a~z的字符

滿足? p[j] == s[i] && dp[i-1][j-1] == true 時dp[i][j]為真(當前和之前所有位置都為真)

②p[j]是字符.

滿足dp[i-1][j-1]==true,則dp[i][j]為真(只要之前均為真,.必可使最后一個位置也相同)

③p[j]是*?

③①p[j-1]是.

③①①.*表示空串

  • 此時p[j-1]和p[j]位置報廢,若dp[i][j-2]為真則dp[i][j]為真,即p的[0,j-2]范圍內的字符能否與s的[0,i]范圍內的字符匹配

③①②.*表示一個.

  • 此時p[j]位置報廢p[j-1]位置為.若dp[i-1][j-2]為真則dp[i][j]為真,即p的[0,j-2]范圍內的字符能否與s的[0,i-1]范圍內的字符匹配,因為p[j-1]位置的.能表示任意字符,故s[i-1]位置不論是什么字符dp[i-1][j-1]一定為真

③①③.*表示兩個.

  • 此時p[j]和p[j-1]位置均為.若dp[i-2][j-2]為真則dp[i][j]為真,即p的[0,j-2]范圍內的字符能否與s的[0,i-2]范圍內的字符匹配,因為p[j]和p[j-1]位置的.能表示任意字符,故s[i]h和s[i-1]位置不論是什么字符dp[i][j]和dp[i-1][j-1]一定為真

③①④.*表示三個.

  • 此時p[j]和p[j-1]均為甚至p[j+1]位置均為.若dp[i-3][j-2]為真則dp[i][j]為真,即p的[0,j-2]范圍內的字符能否與s的[0,i-3]范圍內的字符匹配...(都一樣不重復解釋了)

p[j-1]是a~z的字符

②①字符*表示空串

  • 此時p[j-1]和p[j]位置報廢,若dp[i][j-2]為真則dp[i][j]為真(與上面一樣了,不解釋了)

③②②判斷j-1位置的字符是否與i位置相同(p[j-1] == s[i])

  • 相同則保留字符*的狀態,此時若dp[i-1][j]為真則dp[i][j]為真因為s[j-1]位置上的字符與i位置匹配后因為可以用*造出很多個該字符,所以只需考慮p[0,j]范圍內的字符能否與s[0,i-1]范圍內的字符匹配即可(而判斷這一個范圍內的情況,就需要再次到③②②這種情況來進行判斷),如果均匹配則讓*造字符時多加一個該字符即可

優化③①情況

優化結果:當p[j]為*、p[j-1]為.時,dp[i][j] = dp[i][j-2] || dp[i-1][j]

初步分析:由③①中的多條結論可以得出,當滿足其中一個結論時,dp[i][j]就為真,因為此時p[j-1]和p[j]的組合為.*,如果dp[i][j-2]為真,那么.*只需要創建出一個.即可,如果dp[i-3][j-2]為真,那么.*只需要創建出三個.即可,即只要前面的相等,后面的.*就絕對可以保證后面的所有都相等,即:①p[j] == '*'時,dp[i][j] = dp[i][j-2] ||??dp[i-1][j-2] || dp[i-2][j-2] ...,但是這個式子還是有點長,那么是否能繼續化簡一下?

數學化簡分析

我們令i=i-1,重新套入上面的式子可得:

②p[j] == '*'時,dp[i-1][j] = dp[i-1][j-2] ||??dp[i-2][j-2] || dp[i-3][j-2] ...

我們發現,滿足dp[i-1][j]為真需要滿足dp[i-1][j-2] ||??dp[i-2][j-2] || dp[i-3][j-2] ...的某個條件為真,而該條件與①中的后半部分完全相同,由簡單的數學等價替換就可以得到我們優化③①情況的優化結果

結合實際情況畫圖化簡分析

當p[j]為*、p[j-1]為.時,我們可以分為兩種情況:

情況一:當.*組合與s[i]相同后后不變化仍然保留.*組合,接著比較s[i-1],如果dp[i-1][j]為真則dp[i][j]為真(s的[0,i-1]范圍內的字符與p[0,j]范圍內的字符可以匹配)

情況二:將.*視為一個空串,那么此時如果dp[i][j-2]為真,則dp[i][j]也就為真

總結

1、①和②可以總結為一種情況:當p[j]==s[i]?或者 p[j]==.?為真 且dp[i-1][j-1]為真(兩個的末尾都匹配了 或者 p的末尾為.時無論s的末尾為什么字符都能匹配),那么dp[i][j]就為真

2、③可以總結為:當 dp[i][j-2] 為真或者?(p[j-1] == '.' || p[j-1] == s[i])一個為真且?dp[i-1][j] 為真,則dp[i][j]為真(整合后p[j]==*時引發的所有結論,可以發現這些結論的本質就是圍繞p[j-1]*的組合是空串還是非空串進行研究并得出結論的)

  • p[j-1]*的組合為空:由上圖的分析得,當p[j]為*時一定有“某字符*”是空串的情況,故可以將③①和③②為空的情況合并得到判斷dp[i][j]是否為空的一個條件dp[i][j-2]
  • p[j-1]*的組合不為空:當p[j-1]為.時該組合為“.*”,此時只要dp[i-1][j]為真即可(上面優化里的當dp[j]為*、p[j-1]為.時dp[i][j]為真的兩個條件dp[i][j-2] || dp[i-1][j],p[j-1]*組合為空時候占用了一個dp[i][j-2],現在就剩下另一個條件了,當然如果你不信也可以再推一遍),當p[j-1]為a~z的字符時該組合為“a~z的字符*”,此時也是只需要dp[i-1][j]為真即可

最終代碼

class Solution {
public:bool isMatch(string s, string p) {int m = s.size(),n = p.size();//二者大小不一樣相同//1、創建dp表vector<vector<bool>> dp(m+1,vector<bool>(n+1));//創建一個m行n列的dp表,+1是為了創建輔助行//2、初始化s = ' ' + s,p = ' ' + p;//加上一行輔助位,此時字符串下標和dp表下標一致,不需要在填表時做下標-1的操作//先填寫左上角的輔助行為true,處理特殊情況,即當s為空時,根據p中字符*的情況得到匹配結果(準備工作)dp[0][0] =true;//更新dp表for(int j = 2;j<=n;j+=2)if(p[j]=='*') dp[0][j] =true;else break;//3、填表for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){//p[j]為*L:③的所有情況得到的結論if(p[j] == '*'){dp[i][j] = dp[i][j-2] || (p[j-1] == '.' || p[j-1] == s[i]) && dp[i-1][j];}//p[j]不為*:①②兩種情況得到的結論else{dp[i][j] = (p[j] == s[i] || p[j] == '.')&&dp[i-1][j-1];}}}//4、返回值return dp[m][n];//題目要求的是完全匹配,所以判斷范圍為[0,m]和[0,n];}
};

自我總結:動規主要的內容就是確認狀態表示和狀態轉移方程,由特例推廣至全部,只需要直到宏觀規律即可

~over~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21151.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21151.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21151.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

方法引用與構造方法引用

目錄 方法引用 什么是方法引用 構造方法引用 構造方法引用&#xff08;也可以稱作構造器引用&#xff09; 數組構造方法引用 方法引用 什么是方法引用 當要傳遞給 Lambda 體的操作&#xff0c;已經有實現的方法了&#xff0c;可以使用方法引用。 方法引用可以看做是 La…

PHAR反序列化

PHAR PHAR&#xff08;PHP Archive&#xff09;文件是一種歸檔文件格式&#xff0c;phar文件本質上是一種壓縮文件&#xff0c;會以序列化的形式存儲用戶自定義的meta-data。當受影響的文件操作函數調用phar文件時&#xff0c;會自動反序列化meta-data內的內容,這里就是我們反序…

頭歌頁面置換算法第3關:計算LRU算法缺頁率

2 任務:LRU算法 2.1 任務描述 設計LRU頁面置換算法模擬程序:從鍵盤輸入訪問串。計算LRU算法在不同內存頁框數時的缺頁數和缺頁率。要求程序模擬駐留集變化過程,即能模擬頁框裝入與釋放過程。 2.2任務要求 輸入串長度作為總頁框數目,補充程序完成LRU算法。 2.3算法思路 LRU算…

jmeter常用的斷言

包括&#xff08;Contains&#xff09;&#xff1a;響應內容包括需要匹配的內容即代表響應成功&#xff0c;支持正則表達式 匹配&#xff08;Matches&#xff09;&#xff1a;響應內容要完全匹配需要匹配的內容即代表響應成功&#xff0c;大小寫不敏感&#xff0c;支持正則表達…

vue html2canvas生成base64圖片和圖片高度

vue html2canvas生成圖片 exportAsBase64() {const ele document.getElementById(content);html2canvas(ele, {dpi: 96, // 分辨率 scale: 2, // 設置縮放 useCORS: true, // 允許canvas畫布內跨域請求外部鏈接圖片 bgcolor: #ffffff, // 背景顏色 logging: false, // 不…

rust之cargo install cargo-binstall 是什么

cargo-binstall 是什么 官方&#xff1a;https://lib.rs/crates/cargo-binstall Binstall 提供了一種低復雜性的機制來安裝 Rust 二進制文件&#xff0c;作為從源代碼&#xff08;通過 cargo install &#xff09;構建或手動下載軟件包的替代方案。這旨在與現有的 CI 工件和基…

Windows安裝ElasticSearch版本7.17.0

在Windows系統上本地安裝Elasticsearch的詳細步驟如下&#xff1a; 1. 下載Elasticsearch 訪問 Elasticsearch下載頁面。選擇適用于Windows的版本7.17.0&#xff0c;并下載ZIP文件。 2. 解壓文件 下載完成后&#xff0c;找到ZIP文件&#xff08;例如 elasticsearch-7.17.0.…

【算法篇】冒泡排序算法JavaScript版

冒泡排序算法&#xff1a;原理與實現 冒泡排序&#xff08;Bubble Sort&#xff09;是一種簡單的排序算法&#xff0c;它重復地遍歷要排序的數列&#xff0c;一次比較兩個元素&#xff0c;如果它們的順序錯誤就把它們交換過來。遍歷數列的工作是重復地進行直到沒有再需要交換&…

spoon基礎使用-第一個轉換文件

新建一個轉換&#xff0c;文件->新建->轉換&#xff0c;也可以直接ctralN新建。 從右邊主對象樹拖拽一個輸入->表輸入&#xff1b;輸出->文本文檔輸出&#xff1b;也可以直接在搜索框搜素表輸入、文本文檔輸出。 雙擊表輸入新建一個數據庫連接 確定后就可以在S…

【人工智能】第二部分:ChatGPT的架構設計和訓練過程

人不走空 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌賦&#xff1a;斯是陋室&#xff0c;惟吾德馨 目錄 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌…

Java | Leetcode Java題解之第126題單詞接龍II

題目&#xff1a; 題解&#xff1a; class Solution {public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {List<List<String>> res new ArrayList<>();// 因為需要快速判斷擴展出的單詞…

傳輸中的串擾(八)

串擾指的是有害信號從一個線網傳遞到相鄰線網上。通常把噪聲源所在的線網稱為動態線或攻擊線網&#xff0c;而把有噪聲形成的線網稱為靜態線或受害線網。 靜態線上的噪聲電壓的表現與信號電壓完全一樣。一旦在靜態線上產生噪聲電壓&#xff0c;它們就會傳播并在阻抗突變處出現反…

html解決瀏覽器記住密碼輸入框的問題

當瀏覽器記住密碼并自動填充到表單的密碼輸入框時&#xff0c;這通常是瀏覽器為了提供便利而采取的功能。然而&#xff0c;有時這可能不是用戶所期望的&#xff0c;或者你可能希望在某些情況下禁用此功能。 雖然HTML本身并沒有直接提供禁用瀏覽器自動填充密碼輸入框的標準方法…

常見算法(基本查找、二分查找、分塊查找冒泡、選擇、插入、快速排序和遞歸算法)

一、常見算法-01-基本、二分、插值和斐波那契查找 1、基本查找/順序查找 需求1&#xff1a;定義一個方法利用基本查找&#xff0c;查詢某個元素是否存在 數據如下&#xff1a;{131&#xff0c;127&#xff0c;147&#xff0c;81&#xff0c;103&#xff0c;23&#xff0c;7&am…

Leetcode 3170. Lexicographically Minimum String After Removing Stars

Leetcode 3170. Lexicographically Minimum String After Removing Stars 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3170. Lexicographically Minimum String After Removing Stars 1. 解題思路 這一題的話只需要維護一個有序數列&#xff08;這里我們用堆排來處理&…

C++ C (1152) : 循環賽日程表

文章目錄 一、題目描述二、參考代碼 一、題目描述 二、參考代碼 #include<iostream> #include<vector> #include<cstdlib> using namespace std;void generateSchedule(vector< vector<int> >& table, int numPlayers, int rounds) {// 生…

堆排序-java

這次主要講了堆排序和堆的基本構造&#xff0c;下一期會詳細講述堆的各種基本操作。 文章目錄 前言 一、堆排序 1.題目描述 2.堆 二、算法思路 1.堆的存儲 2. 結點下移down 3.結點上移up 4.堆的基本操作 5.堆的初始化 三、代碼如下 1.代碼如下&#xff1a; 2.讀入數據&#xff…

Harmony os Next——關系型數據庫relationalStore.RdbStore的使用

Harmony os Next——關系型數據庫relationalStore.RdbStore的使用 描述數據庫的使用建表定義表信息創建數據庫表 創建數據庫操作對象增更新查詢刪數據庫的初始化 描述 本文通過存儲一個簡單的用戶信息到數據庫中為例&#xff0c;進行闡述relationalStore.RdbStore數據庫的CRUD…

小公司的軟件開發IT工具箱

目錄 工具鏈困境 難題的解決 達到的效果 資源要求低 工具箱一覽 1、代碼管理工具 2、自動化發版&#xff08;測試&#xff09;工具 3、依賴庫&#xff08;制品包&#xff09;管理 4、鏡像管理 5、授權管理&#xff08;可選&#xff09; 待討論&#xff1a;為什么不是…

LeetCode17電話號碼的字母組合

題目描述 給定一個僅包含數字 2-9 的字符串&#xff0c;返回所有它能表示的字母組合。答案可以按 任意順序 返回。 給出數字到字母的映射如下&#xff08;與電話按鍵相同&#xff09;。注意 1 不對應任何字母。 解析 廣度優先遍歷或者深度優先遍歷兩種方式&#xff0c;廣度優先…