1. 程式人生 > 實用技巧 >44. 萬用字元匹配(Wildcard Matching)

44. 萬用字元匹配(Wildcard Matching)

題目描述:

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

'?' 可以匹配任何單個字元。
'*' 可以匹配任意字串(包括空字串)。
兩個字串完全匹配才算匹配成功。

說明:

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

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

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

解題思路:

  這道題可以用dp解決,dp[i][j]就表示以字元s[i-1]和p[j-1]結尾的子串是夠能夠匹配。注意dp的邊界條件,即s或p為空串時的狀態。如果s為空p為空則為真;如果s不為空但p為空則一定為假;如果s為空但是p都是由‘*’組成,那麼為真,反之為假。

  狀態轉移分為三種情況,第一種是s[i]和p[j]相同,那麼dp[i+1][j+1]的值就等於dp[i][j];第二種情況是p[j]等於‘?’,那麼p[i+1][j+1]的值同樣等於dp[i][j];第三種情況稍微複雜,當p[j]等於‘*’時,這時可以考慮需要p[j]和不需要p[j]兩種情況。如果不需要p[j],那麼dp[i+1][j]為真,則dp[i+1][j+1]為真;如果需要p[j],則p[i][j+1]為真,則dp[i+1][j+1]為真,兩種情況滿足任意一種都可以保證dp[i+1][j+1]為真,所以使用或運算。

  結果返回dp最後一個元素即可。

  程式碼如下:

class Solution
{
public:
    bool isMatch(string s, string p)
    {
        vector<vector<int>> dp{s.size() + 1, vector<int>(p.size() + 1)};
        dp[0][0] = 1;
        for (int i = 0; i < p.size(); ++i)
        {
            if (p[i] == '*')
                dp[0][i + 1
] = 1; else break; } for (int i = 0; i < s.size(); ++i) for (int j = 0; j < p.size(); ++j) { if (s[i] == p[j] || p[j] == '?') dp[i + 1][j + 1] = dp[i][j]; else if (p[j] == '*') dp[i + 1][j + 1] = dp[i + 1][j] | dp[i][j + 1]; } return dp.back().back(); } };