1. 程式人生 > >44.wildcard-matching

44.wildcard-matching

      這道題也是正則表示式類的題目,和10題有很大程度的相似度,個人感覺難度上來講,這道題要簡單一點,有一點需要注意的是這道題不能用遞迴來解決,看到有個測試用例會超時,但也可能是我自己的思路上有缺陷,如果有大神,肯請指點。

      這道題是*號表示任何字串包括空串:"",?表示可以與任意一個字串匹配,所以,最特殊的還是*號,我們分情況討論,

1、假設當前p[i] = s[j] 或者 p[i] == '?',則所以同時加一。

2、假設當前p[i] == '*',則,記錄當前位置的下一個位置點。s的索引值不動,主要是為了涵蓋*號代表空串的情況。p的索引值+1。

3、假設當前失配,即以上兩種情況都不是,則尋找上一個*號記錄點,將p串的索引和s串的索引都重新放在上一個索引點處的下一個位置,讓*號代表長的字串,尋找可能的匹配情況。

4、如果發生失配的情況下依然未能找到有*號記錄,則說明無法完成字串匹配,返回false。

以下是AC程式碼:

class Solution {
public:
    bool isMatch(string s, string p) {
        int pindex = 0, sindex = 0, sstart = 0, pstart = 0;
        while (sindex < s.size()) {
            if (p[pindex] == s[sindex] || p[pindex] == '?') {
                ++pindex;
                ++sindex;
            } else if (p[pindex] == '*') {
                pstart = ++pindex;
                sstart = sindex;
            } else if (pstart) {
                pindex = pstart;
                sindex = ++sstart;
            } else {
                return 0;
            }
        }
        while (pindex<p.size() && p[pindex]=='*') {
            ++pindex;
        }
        return pindex==p.size();
    }
};

 

這道題要說一點的是,遞迴程式之所以會出現超時問題,重要的原因在於一旦出現連續的*號,就會讓複雜度增加很多。其實在本題目中,連續的*號在某種意義上是等價存在的。其實只需要記錄最新的一個即可。如果要使用遞迴,可以嘗試先處理一下多個連續*號,然後在進行遞迴操作。

以下是遞迴程式碼,會發生超時,但思想和10題完全一樣:

class Solution {
public:
    bool isMatch(string s, string p) {
        if (p.empty()) return s.empty();

        if (p[0] == '*') {
            return (isMatch(s, p.substr(1)) || (!s.empty() && isMatch(s.substr(1), p)));
        } else {
            return (!s.empty() && (s[0]==p[0]||p[0]=='?') && isMatch(s.substr(1), p.substr(1)));
        }
    }
};