【LeetCode】44. Wildcard Matching

题目:

Given an input string (s) and a pattern (p), 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).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like ? or *.

Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input:
s = "aa"
p = "*"
Output: true
Explanation: '*' matches any sequence.

Example 3:

Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.

Example 4:

Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".

Example 5:

Input:
s = "acdcb"
p = "a*c?b"
Output: false

 

描述:

给出一个字符串和一个模式串,判断模式串是否能匹配所给字符串,其中:

? 能匹配任意单个字符,* 能匹配任意长度的字符串(包含空串)

 

分析:

除了递归,想不到别的方法,错了很多次以后,调通了,但是却是超时.....(见代码一)

实在是想不到解法了,学习别人的思路吧

线性时间的题解的做法是:(见代码二)

将所有的 * 先视为不存在,然后进行两串匹配,若某个位置匹配失败,则尝试利用距离当前失配位置最近的一个 * 去匹配失配的主串元素,即从主串中下一个能和模式串中当前位置匹配的位置开始匹配,若匹配成功,则返回true,若匹配失败,则再选择稍后位置中下一个能和 * 后元素匹配的位置进行匹配,直到程序结束。

 

测试数据:(有点多...)

"abbabaaabbabbaababbabbbbbabbbabbbabaaaaababababbbabababaabbababaabbbbbbaaaabababbbaabbbbaabbbbababababbaabbaababaabbbababababbbbaaabbbbbabaaaabbababbbbaababaabbababbbbbababbbabaaaaaaaabbbbbaabaaababaaaabb"
"**aa*****ba*a*bb**aa*ab****a*aaaaaa***a*aaaa**bbabb*b*b**aaaaaaaaa*a********ba*bbb***a*ba*bb*bb**a*b*bb"
"aaabbbaabaaaaababaabaaabbabbbbbbbbaabababbabbbaaaaba"
"a*******b"
"c"
"*c?*"
"b"
"?*?"
"ho"
"ho**"
"acdcb"
"a*c?b"
"c"
"*?*"
"c"
"**c*"
""
"*"
"aa"
"**a"
""
""
"a"
""
""
"?"
"aa"
"*"
"abceb"
"*a*b"
"cb"
"?a"
"a"
"?"
"aa"
"a"
"cb"
"?b"

 

代码一:(暴力递归,超时)

class Solution {
public:
	bool isMatch(string s, string p) {
		p = compress(p);
		return tryMatch(s, p , 0, 0);
	}
	string compress(const string &p) {
		string result;
		for (int i = 0; i < p.size(); ++ i) {
			if (result.size() && result[result.size() - 1] == '*' && p[i] == '*') {
				continue;
			}
			result.push_back(p[i]);
		}
        return result;
	}
	bool tryMatch(const string &s, const string &p, int i, int j) {
		while (i < s.size() && j < p.size()) {
			if (s[i] == p[j] || p[j] == '?') {
				++ i;
				++ j;//匹配成功
			} else if (p[j] == '*') {
				return tryMatchStar(s, p, i, j + 1);
			} else {
				return false;
			}
		}
		if (i == s.size()) {
			return allStar(p, j);
		}
		return j != p.size();
	}
	
	bool tryMatchStar(const string &s, const string &p, int i, int j) {
		if (j == p.size()) {//*后边没有任何元素,必定匹配成功
			return true;
		}
		while (i < s.size()) {
			if (p[j] == '*' && tryMatchStar(s, p, i, j + 1)) {
				return true;
			} else if ((p[j] == '?' || s[i] == p[j]) && tryMatch(s, p, i, j)) {
				return true;
			}
			++ i;
		}
		return allStar(p, j);
	}
	bool allStar(const string &p, int index) {
		for (int i = index; i < p.size(); ++ i) {
			if (p[i] != '*') {
				return false;
			}
		}
		return true;
	}
};

 

代码二: (时间复杂度 O ( n + m),n,m 分别为两个串的长度)

class Solution {
public:
	bool isMatch(string s, string p) {
		int i = 0, j = 0, star = -1, current = 0;
		while (i < s.size()) {
			if (s[i] == p[j] || p[j] == '?') {
				++ i;
				++ j;
			} else if (p[j] == '*') {
				star = j;
				current = i;
				++ j;
			} else if (star != -1) {//匹配失败但星号存在
				i = current + 1;
				j = star + 1;
				++ current;
			} else {
				break;
			}
		}
		return i == s.size() && allStar(p, j);
	}
	
	bool allStar(const string &p, int index) {
		for (int i = index; i < p.size(); ++ i) {
			if (p[i] != '*') {
				return false;
			}
		}
		return true;
	}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值