标签:
这道题是一道类似正则表达式匹配的题目,但是我发现这个题的难度比之前那个题的难度高几个档次。如题目所示:‘?‘可以匹配任意一个字符,而 ‘ * ‘ 则可以匹配任意一个字符串,给你两个字符串,主串和模式串,判断他们是否可以匹配。
这道题的难度在于‘*’的处理,到底‘*’要和多少个字符串匹配呢?这个问题不好解决,我一开始的思路是:
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'); } };结果如下:
标签:
原文地址:http://blog.csdn.net/zr1076311296/article/details/51426886