1. 程式人生 > >[LeetCode] Wildcard Matching 外卡匹配

[LeetCode] Wildcard Matching 外卡匹配

Implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

這道題萬用字元匹配問題還是小有難度的,這道里用了貪婪演算法Greedy Alogrithm來解,由於有特殊字元*和?,其中?能代替任何字元,*能代替任何字串,那麼我們需要定義幾個額外的指標,其中scur和pcur分別指向當前遍歷到的字元,再定義pstar指向p中最後一個*的位置,sstar指向此時對應的s的位置,具體演算法如下:

- 定義scur, pcur, sstar, pstar

- 如果*scur存在

  - 如果*scur等於*pcur或者*pcur為 '?',則scur和pcur都自增1

  - 如果*pcur為'*',則pstar指向pcur位置,pcur自增1,且sstar指向scur

  - 如果pstar存在,則pcur指向pstar的下一個位置,scur指向sstar自增1後的位置

- 如果pcur為'*',則pcur自增1

- 若*pcur存在,返回False,若不存在,返回True

C 解法一:

bool isMatch(char *s, char *p) {
    char *scur = s, *pcur = p, *sstar = NULL, *pstar = NULL;
    while (*scur) {
        if (*scur == *pcur || *pcur == '?') {
            ++scur;
            
++pcur; } else if (*pcur == '*') { pstar = pcur++; sstar = scur; } else if (pstar) { pcur = pstar + 1; scur = ++sstar; } else return false; } while (*pcur == '*') ++pcur; return !*pcur; }

這道題也能用動態規劃Dynamic Programming來解,寫法跟之前那道題Regular Expression Matching很像,但是還是不一樣。外卡匹配和正則匹配最大的區別就是在星號的使用規則上,對於正則匹配來說,星號不能單獨存在,前面必須要有一個字元,而星號存在的意義就是表明前面這個字元的個數可以是任意個,包括0個,那麼就是說即使前面這個字元並沒有在s中出現過也無所謂,只要後面的能匹配上就可以了。而外卡匹配就不是這樣的,外卡匹配中的星號跟前面的字元沒有半毛錢關係,如果前面的字元沒有匹配上,那麼直接返回false了,根本不用管星號。而星號存在的作用是可以表示任意的字串,當然只是當匹配字串缺少一些字元的時候起作用,當匹配字串包含目標字串沒有的字元時,將無法成功匹配。

C++ 解法二:

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

類似題目:

參考資料: