您的位置:首页 > 其它

LeetCode - Wildcard Matching

2014-02-28 02:06 344 查看
Wildcard Matching

2014.2.28 01:49

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


Solution:

  At first I tried to implement an O(n * m) solution with dynamic programming and a 2d array, but it proved to be neither efficient nor easy-to-write. I gave up.

  '*' is the key point in wildcard matching, because you can skip arbitrary number of letters when '*' is encountered, while for other letter or '?' you always go one step forward.

  Let's think about what you do when a mismatch happens: s[]="abcde" p[]="abcf". You can't just return false, because '*' means more possibilities.

  See this: s[]="abcxxadc" p="abc*abc". The bold part is the longest match, and the italic is unabled to be matched.

  If you find a letter in p is mismatched, you can seek the last '*' and start searching from the next letter to that '*'. Consecutive '*'s are regarded as one.

  Why is this backtracking correct? Because you can cover those consecutive mismatched letters with one '*', as long as there is one '*' available. Those non-star letters have to be strictly matched.

  The algorithm requires the pattern to be completely matched, so partial match is considered mismatch.

  Total time complexity is O(len(s) + len(p)). Space complexity is O(1).

Accepted code:

// 2CE, 4WA, 1AC, O(m + n) solution, not so easy to understand.
#include <cstring>
using namespace std;

class Solution {
public:
bool isMatch(const char *s, const char *p) {
if (s == nullptr || p == nullptr) {
return false;
}

int ls, lp;

ls = strlen(s);
lp = strlen(p);

if (ls == lp && lp == 0) {
return true;
}

if (lp == 0) {
return false;
}

// from here on, ls and lp are guaranteed to be non-zero.
int i, j;
int last_star_p;
int last_star_s;

i = j = 0;
last_star_p = -1;
last_star_s = 0;
while (j < ls) {
if (p[i] == '?' || p[i] == s[j]) {
++i;
++j;
} else if (p[i] == '*') {
last_star_p = i;
++i;
last_star_s = j;
} else if (last_star_p != -1) {
// backtrack to the last '*', and move to the next letter in s
i = last_star_p + 1;
j = last_star_s + 1;
++last_star_s;
} else {
return false;
}
}
while (p[i] == '*') {
// skip the trailing stars
++i;
}

return i == lp;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: