1. 程式人生 > >【leetCode】44_萬用字元匹配

【leetCode】44_萬用字元匹配

dp:

class Solution {
public:
    bool isMatch(string s, string p) {
        //tag 用於dp,tag[i][j]代表s的子串s[0,i-1] 可以匹配 p的子串p[0,j-1]。
        bool ** tag = new bool*[s.length() + 1];
        for (int i = 0; i <= s.length(); i ++){
            tag[i] = new bool [p.length() + 1];
            memset(tag[i], 0, sizeof(bool) * (p.length() + 1));
        }
        //tag[0][0]初始化條件,可以理解成,s和p的子串s[0,-1], p[0,-1]匹配,即兩個空串匹配。
        tag[0][0] = true;
        //dp的遞推方程是:tag[i][j] = 
        // (1)p[j - 1] == '*', 則為:tag[i - 1][j - 1] || tag[i][j - 1] || tag[i - 1][j];
        // (2)為:tag[i - 1][j - 1] && (p[j - 1] == '?' ? 1: p[j - 1] == s[i - 1])
        for (int j = 1; j <= p.length(); j ++){
            for (int i = 0; i <= s.length(); i ++){
                if (p[j - 1] == '*'){
                    tag[i][j] = (i > 0 ? (tag[i - 1][j - 1]||tag[i - 1][j]): 0) || tag[i][j - 1];
                }
                else if (i != 0){
                    tag[i][j] = tag[i - 1][j - 1] && (p[j - 1] == '?' ? 1: p[j - 1] == s[i - 1]);
                }
            }
        }
        return tag[s.length()][p.length()];
    }
};

帶回溯的貪心:

思路是*字元匹配的時候,可以匹配0~無窮多個字元。所以,列舉s串被匹配的字元數量。

方法是匹配到*的時候,記錄下s和p的位置s*和p*,給p的位置+1, s位置不變,此時*匹配0個字元,然後s和p繼續匹配之後的字串。如果匹配不成功,回溯,p的匹配位置更改回p*+1,s的位置更改為記錄s*+1,此時*匹配1個字元然後s和p繼續匹配之後的字元。依此類推。

class Solution {
public:
    bool isMatch(string s, string p) {
        int scur = 0, pcur = 0, sstar = -1, pstar = -1;
        while(scur != s.length()){
            if (s[scur] == p[pcur] || p[pcur] == '?'){
                scur ++; pcur ++;
            }
            else if (p[pcur] == '*'){
                pstar = pcur ++;
                sstar = scur;
            }
            else if (pstar != -1){
                pcur = pstar + 1;
                scur = ++ sstar;
            }
            else{
                return false;
            }
        }
        while (p[pcur] == '*'){
            pcur ++;
        }
        return pcur == p.length();
    }
};