LeetCode:Wildcard Matching

leetcode:Wildcard Matching 

题目

链接:https://oj.leetcode.com/problems/wildcard-matching/
描述:寻找一种字符串的匹配模式,匹配规则:
1. '?'可以匹配任意一个字符;
2. '*'可以匹配任意字符串,可以匹配空串。
例子:
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

思路

从左到右字符一个一个匹配,这里难的是关于'*'的匹配,其他都还好,注意到如果一个字符串A+B(A是一个字符串,B是另一个)匹配字符串*+B,那么任何A的尾巴+B 都应该是可以匹配到*+B的,所以可以产生一种递归。如果当前字符遇到*,那么它后面知道真正于模式匹配的那个字符之前都是可以匹配当前模式的,所以可以递归调用isMatch(s+1,p)得到的结果应该是和isMatch(s,p)相同的,如果不同就可以返回false,也就是不匹配。

递归代码(TLM)

使用递归的方法可以写出下面代码。
bool isMatch(const char * s, const char * p)
{
	
	while(*s != '\0' && *p != '\0')
	{
		cout<<"Here! "<<s<<", "<<p<<endl;
		if (*s == *p || *p == '?') 
		{
			s++;p++;
		}
		if (*p == '*')
		{
			while(*p == '*' || *p == '?') p++;
			if (*p == '\0')
			{
				return true;
			}

			while(*s != '\0')
			{
				while(*s != '\0' && *s != *p) s++; //将所有可以匹配到下一个字符串的字符串都遍历一遍,如果都不符合就false
				if (isMatch( ++s,p + 1))
				{
					return true;
				}
			}
			return false;
		}
		if (*s != *p)
		{
			return false;
		}
	}
	if (*s != '\0')
	{
		return false;
	}
	while(*p != '\0' && *p == '*')p++;
	if (*p != '\0')
	 {
	 	return false;
	 } 
	return true;
}

迭代代码

这种递归深度太深,所以肯定会超时,所以必须优化,剔除那些重复的操作,不用递归。
采用迭代的思想,首先,正常匹配所有其他非*字符,等遇到*记录*出现,今后遇到不匹配的可以使用*号抵消,一直将遇到*之后的不和模式匹配的字符都抵消掉,,一直到最终整个字符串都遍历完毕,如果模式串,也同样只剩下*,那么就匹配成功,如果不能将模式串完全用尽,那么就是false。代码如下
bool isMatch(const char * s, const char * p)
{
	bool flag = false;
	const char * pstr;
	const char * sstr;
	while(*s != '\0')
	{

		//cout<<"Here! "<<s<<", "<<p<<endl;

		if (*s == *p || *p == '?')
		{
			s++;p++;
		}
		else if (*p == '*')
		{
			flag = true;
			pstr = p;
			sstr = s;
			while(*pstr == '*') pstr++;
			if (*pstr == '\0')
			{
				return true;
			}
			p = pstr;
		}
		else if (*s != *p )
		{
			if(!flag) return false;
			sstr++;
			s = sstr;
			p = pstr;
		}
	}
	if (*s != '\0')
	{
		return false;
	}
	while(*p != '\0' && *p == '*')p++;
	if (*p != '\0')
	 {
	 	return false;
	 }
	return true;
}

代码参考了github上一位大牛的思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值