笔试题57. LeetCode OJ (44)

Posted _从未止步

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔试题57. LeetCode OJ (44)相关的知识,希望对你有一定的参考价值。

        这道题是一道类似正则表达式匹配的题目,但是我发现这个题的难度比之前那个题的难度高几个档次。如题目所示:'?'可以匹配任意一个字符,而 ' * ' 则可以匹配任意一个字符串,给你两个字符串,主串和模式串,判断他们是否可以匹配。

     这道题的难度在于‘*’的处理,到底‘*’要和多少个字符串匹配呢?这个问题不好解决,我一开始的思路是:

1.遇到s[i] = p[i] || p[i] =='?' 这两种情况,两者都前进一位

2.遇到s[i] != p[i] 的时候,看前面是否有‘*’,若无则直接返回false,若有的话就比较麻烦了...

3.遇到p中的‘*’时,在p后面找一个字符串,找其在s中第一次出现的下标,继续;若失败则回溯,找第二次出现的下标...

这样的思路会用到KMP算法,而且回溯的位置也太难控制,所以我决定放弃,我又想了很久,没有思路,后来不得不看看网友的思路,在他们的解题中,我发现了,这个题需要明白一件事!


        好了讲到这里就比较清晰了,看代码吧!

class Solution {
public:
	bool isMatch(string s, string p)
	{
	    /*
	        这道题要想清楚思路,我一开始的思路是遇到*号的时候,在s[i~s.s.len]内查找p[i~p[j] == '*' || p[j] == '?'] 第一次出现的位置,这样比较好判断是否需要继续比较了,但是这样无疑引入了KMP算法,想到这样我就觉得这样的做法不可取,kmp算法本来就比较复杂的,再引入它的话,就加大了难度,这个题和以前做过的正则表达式有些相似,但是这个题却比那个题难,主要是对 * 的分析比较麻烦,这道题采用了循环的做法,因为我感觉若*号太多的话,递归的层数太多了,效率也会被拖下来的。
	    */
	    
		return Match(s.c_str(), p.c_str());
		
	}
	
	bool Match(const char* s, const char* p)
	{
		const char * back = NULL;      //用于标记S中和 P中'*'号对应的位置,从该位置起开始依次查找回溯。
		const char * sequence = NULL;  //标记P中 '*' 出现的位置

		while (*s)
		{
			if (*p == '*')
			{ //若 p 中出现了 ‘*’,则back记录s与其对应的位置(可能是空串),sequence 记录'*'的下一个位置,因为从下一个位置开始查找的
				back = s;
				sequence = ++p;
			}
			else if (*p == '?' || *s == *p)
			{// 这两种情况的话,则 s 和 p 的位置各加1
				++s;
				++p;
			}
			else if (sequence)
			{//说明出现了 '*' 且在查找中不匹配,那么s应该指向back的下一个位置,p 回到原来位置'*'的下一个位置
				s = ++back;
				p = sequence;
			}
			else
			{//没有出现‘*’且不匹配,那么可以直接下结论了,退出!
				return false;
			}
		}

        while(*p == '*')
        {// p的序列中‘*’可能出现在末尾,那么我们应该跳过这些位置
            ++p;
        }
        
        // 最后通过p是否指向最后一个位置来说明true或者false
		return (*p == '\\0');
	}
};
结果如下:



以上是关于笔试题57. LeetCode OJ (44)的主要内容,如果未能解决你的问题,请参考以下文章

笔试题58. LeetCode OJ (45)

笔试题61. LeetCode OJ (48)

笔试题55. LeetCode OJ (42)

笔试题54. LeetCode OJ (41)

笔试题56. LeetCode OJ (43)

笔试题79. LeetCode OJ (66)