1. 程式人生 > 其它 >5.3 Linux Vim三種工作模式

5.3 Linux Vim三種工作模式

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;
    }
};