美文网首页
44. Wildcard Matching

44. Wildcard Matching

作者: Al73r | 来源:发表于2017-10-09 10:36 被阅读0次

题目

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

分析

本来想用递归搜索做,奈何时间复杂度太高,不断超时。递归的代码倒是很好看,辛辛苦苦写的,也贴一下吧=_=

class Solution {
public:
    bool isMatch(string &s, string &p) {
        return solve(s, p, 0, 0);
    }
private:
    bool solve(string &s, string &p, int i, int j){
        if(i==s.size() && j==p.size()) return true;
        if(i==s.size() && p[j]=='*') return solve(s, p, i, j+1);
        if(i==s.size() || j==p.size()) return false;
        if(s[i]==p[j] || p[j]=='?')
            return solve(s, p, i+1, j+1);
        if(j<p.size() && p[j]=='*'){
            while(j<=p.size() && p[j]=='*')
                j++;
            while(i<=s.size()){
                if(solve(s, p, i, j))
                    return true;
                i++;
            }
        }
        return false;
    }
};

接下来是阅读答案的代码。不得不说,代码很简洁,但是感觉很复杂,看了很久也没弄清楚。但是这个过程给了我一些启发:

  • 连续的若干''可以简化为一个''
  • '*'将字符串p分为若干段
  • 这若干段中,第一段需要从s的开头开始匹配,最后一段需要匹配到s的结尾,中间每段只要在s中不重叠地依次出现即可(首段和尾段可以为空)
  • 对于'?'的处理可以放在匹配的部分

所以我的方法是:

  • 首先预处理,根据'*'的位置将p分为若干段
  • 处理首段(如果有的话)
  • 处理中间段(如果还没结束的话)
  • 处理尾段(如果有的话)

而对于匹配的部分,我使用的是朴素的匹配方法,如果引入更高级的方法能够进一步降低时间复杂度。

实现

class Solution {
public:
    bool isMatch(string s, string p) {
        if(p.empty()) return s.empty();
        const char *pc=p.c_str();
        vector<pair<int, int>> strinfo; //(start pos, size)
        int i=0;
        while(i<p.size()){//get strinfo
            if(p[i]=='*'){
                while(i<p.size() && p[i]=='*')
                    i++;
            }
            int count = 0, pos = i;
            while(i<p.size() && p[i]!='*'){
                i++; count++;
            }
            strinfo.push_back(make_pair(pos, count));
        }
        int j=0, pos=0, rlt;
        if(strinfo[j].first==0){//start
            rlt = myfind(s, pc+strinfo[j].first, pos, strinfo[j].second);
            if(rlt==string::npos || rlt!=0) return false;
            pos = rlt + strinfo[j].second;
            j++;
        }
        if(j==strinfo.size()) return pos==s.size();
        while(j<strinfo.size()){//mid
            rlt = myfind(s, pc+strinfo[j].first, pos, strinfo[j].second);
            if(rlt==string::npos) return false;
            pos = rlt + strinfo[j].second;
            j++;
        }
        if(strinfo[j-1].second==0)//end
            return true;
        if(pos==s.size()) return true;
        rlt=myfind(s, pc+strinfo[j-1].first, s.size()-strinfo[j-1].second, strinfo[j-1].second);
        return rlt!=string::npos;
    }
private:
    int myfind(const string &s, const char* p, int pos, int n){
        if(n==0) return pos;
        int i=pos, j=0;
        while(i<s.size()){
            if(s[i]==p[j] || p[j]=='?'){
                i++; j++;
                if(j==n) return pos;
            }
            else{
                pos++;
                i=pos; j=0;
            }
        }
        return string::npos;
    }
};

思考

有时候追求代码的简洁会浪费很多时间,而且可读性也不一定好。
与其纠结于使用漂亮的代码,不如先理清思路,然后按部就班地进行,更加稳妥。

相关文章

网友评论

      本文标题:44. Wildcard Matching

      本文链接:https://www.haomeiwen.com/subject/bsgeyxtx.html