LeetCode 44. 萬用字元匹配

來源:互聯網
上載者:User

標籤:支援   包含   完全   學習   ret   過程   string   遇到   結果   

給定一個字串 (s) 和一個字元模式 (p) ,實現一個支援 ‘?‘ 和 ‘*‘ 的萬用字元匹配。

‘?‘ 可以匹配任何單個字元。‘*‘ 可以匹配任一字元串(包括Null 字元串)。

兩個字串完全符合才算匹配成功。

說明:

  • s 可能為空白,且只包含從 a-z 的小寫字母。
  • p 可能為空白,且只包含從 a-z 的小寫字母,以及字元 ? 和 *

樣本 1:

輸入:s = "aa"p = "a"輸出: false解釋: "a" 無法匹配 "aa" 整個字串。

樣本 2:

輸入:s = "aa"p = "*"輸出: true解釋: ‘*‘ 可以匹配任一字元串。

樣本 3:

輸入:s = "cb"p = "?a"輸出: false解釋: ‘?‘ 可以匹配 ‘c‘, 但第二個 ‘a‘ 無法匹配 ‘b‘。

樣本 4:

輸入:s = "adceb"p = "*a*b"輸出: true解釋: 第一個 ‘*‘ 可以匹配Null 字元串, 第二個 ‘*‘ 可以匹配字串 "dce".

樣本 5:

輸入:s = "acdcb"p = "a*c?b"輸入: false

這個題在很多個Tag下,如DP,貪心,回溯等。

動態規劃

對於兩個字串的問題,容易想到用dp[i][j]這樣的形式來表示狀態。我一開始是定義dp[i][j]為字串s中前i個字元和p中前j個字元是否匹配(i和j從0開始),由於初始化問題弄了很久,最後寫出的代碼異常垃圾。。。

class Solution {public:    bool isMatch(string s, string p) {        if (p.size() == 0 && s.size() == 0) {            return true;        }        if (p.size() == 0) {            return false;        }        else if (p == "*") {            return true;        }        else if (s.size() == 0) {            return false;        }        int row = p.size(), column = s.size();        vector<vector<int>> dp(row);        vector<bool> okDp(row, false);        for (int i = 0; i < row; i++) {            dp[i].resize(column);        }        bool matched = false;        dp[0][0] = (p[0] == ‘*‘ || p[0] == ‘?‘ || p[0] == s[0]) ? 1 : 0;        if (p[0] == ‘?‘ || p[0] == s[0]) {            matched = true;        }        for (int i = 1; i < row; i++) {            if (p[i] == ‘*‘) {                dp[i][0] = dp[i - 1][0];                if (dp[i][0]) {                    okDp[i] = true;                }            }            else if (p[i - 1] == ‘*‘ && p[i] == s[0]) {                dp[i][0] = matched ? 0 : dp[i - 1][0];                matched = true;            }            else if (p[i] == ‘?‘) {                dp[i][0] = matched ? 0 : dp[i - 1][0];                matched = true;            }        }        for (int j = 1; j < column; j++) {            if (p[0] == ‘*‘) {                dp[0][j] = 1;            }        }        for (int i = 1; i < row; i++) {            for (int j = 1; j < column; j++) {                if (isalpha(s[j]) && isalpha(p[i])) {                    if (s[j] == p[i]) {                        dp[i][j] = dp[i - 1][j - 1];                    }                    else {                        dp[i][j] = 0;                    }                }                else if (p[i] == ‘?‘) {                    dp[i][j] = dp[i - 1][j - 1];                }                else if (p[i] == ‘*‘) {                    if (okDp[i] || dp[i - 1][j]) {                        okDp[i] = true;                        dp[i][j] = 1;                    }                }            }        }        return dp[row - 1][column - 1];    }};

後來學習了其他的解法,先上代碼:

class Solution {public:    bool isMatch(string s, string p)     {        int n=s.size();        int m=p.size();        //代表的是  s[0...i]  p[0..j]是否匹配的情況        vector<vector<bool>>dp(n+1,vector<bool>(m+1,false));        dp[0][0]=true;           for(int j=1;j<=m;j++)            dp[0][j]=(p[j-1]==‘*‘?dp[0][j-1]:0);        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)            {                if(i>0&&(s[i-1]==p[j-1]||p[j-1]==‘?‘))                    dp[i][j]=dp[i-1][j-1];                else if(p[j-1]==‘*‘)                {                    dp[i][j]=dp[i-1][j-1]||dp[i-1][j]||dp[i][j-1];                         }                else                     dp[i][j]=0;            }                                                        return dp[n][m];    }                               };

在這裡,狀態dp[i][j]是從1開始計算起來的。一開始不明白為什麼這樣子也行得通,後來考慮到有空串的情況。如""和""對於dp[0][0],""和"*"對於dp[0][1]。這樣子的話初始化就很容易了。

在填表的過程中:

  1. 如果s[i - 1] = p[j - 1],則是字母匹配到了字母,那麼匹配結果取決於前面的匹配結果。
  2. 如果p[j - 1] = ‘?‘,那麼是問號匹配到了字母,也是匹配結果取決於前面的結果。
  3. 如果p[j - 1] = ‘*’,那麼是遇到了星號。星號可能匹配的是空串,那麼就是取決於dp[i][j - 1]的結果。如果匹配了一個字元,那麼就是取決於dp[i - 1][j - 1]。如果匹配了兩個字元,那麼就是取決於dp[i - 2][j - 1]。
    所以,dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 2][j - 1] || ... || dp[0][j - 1]。
    又因為dp[i - 1][j] = dp[i - 1][j - 1] || dp[i - 2][j - 1] || ... || dp[0][j - 1]。
    所以dp[i][j] = dp[i][j - 1] || dp[i - 1][j]。

LeetCode 44. 萬用字元匹配

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.