5.3 Linux Vim三種工作模式
阿新 • • 發佈:2022-05-07
10. 正則表示式匹配
給你一個字串 s
和一個字元規律 p
,請你來實現一個支援 '.'
和 '*'
的正則表示式匹配。
-
'.'
匹配任意單個字元 -
'*'
匹配零個或多個前面的那一個元素
所謂匹配,是要涵蓋 整個 字串 s
的,而不是部分字串。
示例 1:
輸入:s = "aa", p = "a"
輸出:false
解釋:"a" 無法匹配 "aa" 整個字串。
示例 2:
輸入:s = "aa", p = "a*"
輸出:true
解釋:因為 '*' 代表可以匹配零個或多個前面的那一個元素, 在這裡前面的元素就是 'a'。因此,字串 "aa" 可被視為 'a' 重複了一次。
示例 3:
輸入:s = "ab", p = ".*"
輸出:true
解釋:".*" 表示可匹配零個或多個('*')任意字元('.')。
提示:
1 <= s.length <= 20
1 <= p.length <= 30
-
s
只包含從a-z
的小寫字母。 -
p
只包含從a-z
的小寫字母,以及字元.
和*
。 - 保證每次出現字元
*
時,前面都匹配到有效的字元
思路:
正則表示式匹配,經典的動態規劃問題,在《劍指offer》中已經寫過一次,這次再次遇到依然需要去看之前寫過的題解,難免令人尷尬。還需要多加複習。
class Solution { public: //備忘錄 map<string,bool>memo; bool isMatch(string s, string p) { //正則表示式經典動態規劃問題 return dp(s,0,p,0); } //dp表示s[0...]和p[0...]是否能夠匹配 bool dp(string s,int i,string p,int j){ //base case if(j==p.size()){//如果p走完了,那麼只要s也走完那麼就匹配(注意:s走完了,p不一定走完) if(i==s.size())return true; } if(i==s.size()){//s已經走完,但是p沒有走完 //那麼p要怎樣才能走完呢? //'x*'這樣成對 if((p.size()-j)%2==1)return false;//如果剩下的元素數量不是偶數,就一定不符合規則 //如果是偶數就去看是不是'x*'形式 for(;j<p.size();j+=2){ if(p[j+1]!='*')return false; } return true; } //每次判斷前看備忘錄 string key=to_string(i)+','+to_string(j); if(memo.count(key))return memo[key]; bool res=true; //從i和j位置開始判斷 //如果成功判斷 if(s[i]==p[j]||p[j]=='.'){ //如果成功則還要去判斷p的下一位是不是*,可以匹配0或n次 //如果匹配0次則直接跳過p的'.*',如果要匹配多次就繼續去判斷i+1,j不變 兩者有一個成功就行 if(j<p.size()-1&&p[j+1]=='*'){ res=dp(s,i,p,j+2)||dp(s,i+1,p,j); }else{ //如果沒有*存在 res=dp(s,i+1,p,j+1); } }else{ //如果匹配失敗 也有可能是j+1位是*,匹配0次 if(j<p.size()-1&&p[j+1]=='*')return dp(s,i,p,j+2); else{ res=false; } } //寫到這裡可以發現其實是存在重疊子問題的,那麼我們可以記錄s的i位置和p的j位置判斷時的結果 memo[key]=res;//沒有的話map會自己建立 return res; } };