leetcode10 正則表達式匹配(遞歸,動態規划)


  •  用遞歸的算法
  •  
    static const auto __speedup_ = []() {
        std::cout.sync_with_stdio(false);
        std::cin.tie(nullptr);
        return 0;
    }();
    
    /*
        用遞歸的算法:注意邊界條件的討論
    
    
        原問題如下:
        Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
    
        '.' Matches any single character.
        '*' Matches zero or more of the preceding element.
        The matching should cover the entire input string (not partial).
    
        Note:
    
        s could be empty and contains only lowercase letters a-z.
        p could be empty and contains only lowercase letters a-z, and characters like . or *.
    */
    class Solution {
    public:
        // 用p匹配s
        bool isMatch(string s, string p) {
            // p為空時的討論
            if (!p.length() && !s.length())
                return true;
            if (!p.length() && s.length() > 0)
                return false;
    
            // s為空時的討論,只有p為 .*.*.*.*.* 的形式時才能匹配
            if (!s.length())
            {
                if (p.length() % 2 == 1)  return false;
    
                int i = 1;
                while (i < p.length() && p[i] == '*')
                {
                    i += 2;
                }
                if (i == p.length() + 1) return true;
                else return false;
            }
    
            // p[1]為*時,用p+2匹配s+0,s+1,s+2,s+3…………,成功返回true,失敗返回false
            int i = -1;
            if (p.length() >=2 && p[1] == '*')
            {
                do {
                    // 當++i為len+1時截取字符串才會越界報錯,但是++i為len時截取的子串為空就已經返回結果了,所以永遠沒有機會截取len+1
                    if (isMatch(s.substr(++i), p.substr(2)))
                        return true;
                    // 匹配失敗且i已經為len了,即p+2匹配到s的最后了任然匹配失敗,return false
                    else if (i == s.length())
                        return false;
                    // 由於上面的++i截取到len時就會return退出,所以s[i]也永遠不會越界
                } while ((s[i] == p[0] || p[0] == '.'));
                return false;
            }
            // p[1]不為*時    
            else
            {
                if (s[0] == p[0] || p[0] == '.')
                    return isMatch(s.substr(1), p.substr(1));
                else
                    return false;
            }
        }
    };

     

  • 用動態規划的算法
  • /*
        用動態規划的算法:邊界、越界問題最后統一討論
    
    
        原問題如下:
        Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
    
        '.' Matches any single character.
        '*' Matches zero or more of the preceding element.
        The matching should cover the entire input string (not partial).
    
        Note:
    
        s could be empty and contains only lowercase letters a-z.
        p could be empty and contains only lowercase letters a-z, and characters like . or *.
    */
    class Solution {
    public:
        // 用p匹配s
        bool isMatch(string s, string p) {
            // match[i][j]==true 表示s的前i位和p的前j位是匹配的
            vector< vector<bool> > match(s.length() + 3, vector<bool>(p.length() + 3, false));
            
            // 邊界條件為i=0 j=0 j=1
            // j=0時p為空串,只能匹配空串,其他默認為false
            match[0][0] = true;
            // j=1時p只有一個字符,只能匹配一個字符,其他全部為false
            match[1][1] = s[0] == p[0] || p[0] == '.';
            // i=0時s為空串,p只有類似a*b*c*d*這樣的形式才可以成功匹配
            for (int j = 2; j < p.length() + 1; j += 2)
                // 前0位和前j-2位是匹配的,且第j位是*
                match[0][j] = match[0][j - 2] && p[j - 1] == '*';
    
    
            // i表示s的前i位,j表示p的前j為
            for (int i = 1; i < s.length() + 1; i++)
                for (int j = 2; j < p.length() + 1; j++)
                {
                    if (p[j - 1] != '*')
                        // 前i-1位和前j-1位是匹配的,且第i位和第j位是匹配的
                        match[i][j] = match[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
                    else
                        //當p[j-1]出現0次時,前i位和前j-2位是匹配的
                        //當p[j-1]出現1次或多次時,第i位一定匹配第j-1位,且前i-1位一定和前j位是匹配的。
                        match[i][j] = match[i][j - 2] || match[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.');
                }
            return match[s.length()][p.length()];
        }
    };

     

  • 1234234


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM