1. 程式人生 > >leetcode 10. 正則表達式匹配

leetcode 10. 正則表達式匹配

turn 包含 類型 src class nbsp 第一個字符 char* 分享圖片

技術分享圖片

這道題最初刷題連答案都看不懂,實在不是一道容易的題目。

補充兩個C++知識:

1)string對象的.c_str() 返回一個c語言字符串指針 即const char* p類型的指針;

2)c語言字符串的末尾為‘\0’可以用 *p==0 判斷是否到達末尾。

遞歸解法不斷的對當前情況和之後的情況進行判斷:

1)當前匹配字符串p為空,如果此時s為空則return true,s不為空則return false;

2)當前匹配字符串p不為空,那麽對當前p和s進行匹配(不考慮下一位是否有*),結果為match

  2.1)下一位有*時,a和b都有可能有正確的解:

    a)如果正解在a中,即當前字符串應該出現0次,那麽無論當前的match成功與否,return isMatch(s,p.substr(2));

    b)如果正解再b中,即當前字符串至少出現1次,那麽當前至少應該匹配成功,並且還要遞歸求解isMatch(s.substr(1),p.substr(1)),即return match&&isMatch(s.substr(1),p.substr(2));

  2.2 ) 下一位沒有*時,

    a)如果當前匹配成功match==true,那麽匹配下一個字符,即 if(match) return isMatch(s.substr(1),p.substr(2));

    b)如果當前匹配失敗match==false,那麽不用匹配直接return false;

C++ 代碼如下:

一)使用string對象不使用指針

class Solution {
public:
    bool isMatch(string s, string p) {
        //情況1,加入p為空那麽只要s為空那麽得到true反之false
        if(p.empty()) return s.empty();
        //計算當前對應字符的匹配first_match,p不為空,匹配當前第一個字符(不包含s為空而p為a*之類的情況,只探討是否字母直接匹配和.匹配)
bool match=!s.empty()&&(s[0]==p[0] || p[0]==.); //情況2,p當前長度大於2,而且下一個字符是*(p.length()>=2 && p[1]==‘*‘) if(p.length()>=2 && p[1]==*){ // 2.1(*為0個的情況)當前對應位置字符不匹配即first_match==false,那麽p當前字母為0個時還有匹配可能,即s和p.substr(2) //或者當前字符能匹配first_match=true但不合適因此也需要為0個,即s和p.substr(2) // 2.2(*為1個以上的情況)當前對應字符匹配 first_match==true,而且正確答案就在此,那麽匹配s的下一個字符和當前p的字符(因為*代表任意多的情況 return isMatch(s,p.substr(2)) || match && isMatch(s.substr(1),p); }else{ //情況3,如果p只剩下1個,而這時 // 3.1 first_match==true,那麽去決議s.substr(1)和p.substr(1) // 3.2 first_match==false,那麽已經false,不用繼續了 if(match) return isMatch(s.substr(1),p.substr(1)); else return false; } } };

缺點:遞歸過程中,需要不斷的復制儲存子串,因此時間消耗較多,幾百ms

二)使用指針:

// 優化後遞歸的版本,通過傳遞指針省去不斷的復制和存儲 20ms
class Solution {
public:
    bool isMatch(string s, string p) {
        //string對象的.c_str()返回一個c字符串的指針,即const char *
        return isMatch(s.c_str(),p.c_str());
    }
    bool isMatch(const char* s,const char* p){
        //c字符串是以\0結尾的
        if(*p==0) return *s==0;
        
        bool match=(*s!=0) && (*s==*p||*p==.);
        
        if(*(p+1)==*){
            return isMatch(s,p+2)|| match&&isMatch(s+1,p);
        }else{
            return match&&isMatch(s+1,p+1);
        }
    }
};

缺點:使用指針,相對更容易出bug和難以理解

leetcode 10. 正則表達式匹配