LeetCode 44. Wildcard Matching

来源:互联网 发布:qq第三方登录 java 编辑:程序博客网 时间:2024/05/16 11:34
题目:字符串匹配问题

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

分析

这道题看上去与LeetCode 10很像。如果我们用LeetCode 10的解法来解这道题,即考虑’*’可以代替的字符串,替换p中的’*’,与s比较。再通过一些技巧用尽可能少的替换情况来优化,我们得到的依然是一个O(n2)的算法,其中n为s串的长度。但是,需不需要例举这些可能性呢?我们不在乎’*’及’?’被替换成了什么使得s和p能够匹配,而只在乎能不能匹配。

匹配的关键是在s中能够找到p中除’*’外的字符。p可以看做由’*’分割的一个个小字符串,如果这些小字符串在s中能够按照在p中出现的顺序找到,那么s和p匹配,否则不匹配。我们需要做的只是从p中分离出小字符串,按照顺序一个一个在s中查找。如果所有的都找到,则匹配;如果有没有找到的,则不匹配。如果s的长度为n,p中除’*’以外的字符数目为m,那么此算法的复杂度为O(nm)

class Solution {  public:      bool isMatch(string s, string p) {        if (p == "") { return s == ""; }        if (p == "*") { return true; }        string cp;        for (int i = 0; i < p.size(); i++) {            if (p[i] == '*' && cp.size() > 0 && cp[cp.size() - 1] == '*') {                continue;            } else {                cp += p[i];            }        }        string block = "";        int bound = 0;        bool addon = false, fixStart = (cp.size() > 0 && cp[0] != '*');        for (int i = 0; i < cp.size(); i++) {            if (cp[i] != '*') {                if (addon) {                    block += cp[i];                } else {                    addon = true;                    block = "";                    block += cp[i];                }                if (i == cp.size() - 1) {                    if (fixStart) {                        return equal(s, block);                    } else {                        int temp = s.size() - block.size();                        bound = find(s, max(bound, temp), s.size(), block);                    }                    return bound != -1;                }            } else if (addon) {                addon = false;                if (fixStart) {                    fixStart = false;                    bound = find(s, bound, min(s.size(), block.size()), block);                } else {                    bound = find(s, bound, s.size(), block);                }                if (bound == -1) {                    return false;                }            }        }        return true;    }    bool equal(string s, string p) {        int sl = s.size(), pl = p.size();        if (sl != pl) { return false; }        for (int i = 0; i < sl; i++) {            if (s[i] != p[i] && p[i] != '?')                return false;        }        return true;    }    int find(string s, int lower, int upper,  string b) {        int i = lower, j = 0;        while (i < upper) {            if (s[i] == b[j] || b[j] == '?') {                i++;                j++;                if (j == b.size()) {                    return i;                }            } else {                i = i - j + 1;                j = 0;            }        }        return -1;    }};
0 0