1.题目如下:
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
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", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true
这是一个类似于正则表达式的匹配,其中’.’和可以匹配任何单个字符,而’*’可以让它前一个字符重复0次或多次。
注意,我看了论坛,发现有的人无法理解
isMatch("ab", ".*") → true
“.*”可以理解为两个点即”..”,而每个点可以匹配任何字符,前一个匹配”a”,后一个匹配”b”,所以为true。
2.题目分析
这个题目是判断给定的字符是否匹配给定的模式。我们需要同时遍历字符串s和模式串p进行判断,分别用sp和pp表示字符串当前访问的字符和模式串中当前访问的字符。我们可以将匹配过程分为以下几个过程:
1.判断pp的大小是否等于模式串p的长度,即模式串p已经遍历完了;如果不是,转到步骤3;如果是,然后再判断sp是否等于字符串s
的长度,如果是返回True,否则返回false.
2.判断sp大小是否等于字符串s的长度,如果不是,转到步骤3;如果是,判断当前遍历的模式串p的下一个遍历字符是不是'*',如果
是,则将当前遍历的模式串字符向前推进2(跳过这个'*',因为'*'可以表示重复0次),即pp加2;然后转到步骤1;如果不是,返回False。
3.判断当前遍历的字符串字符是否等于当前遍历的模式串字符,如果相等,执行4,否则执行7.
4.判断当前遍历的模式串字符的下一个字符是否等于'*',如果相等执行5,否则执行6.
5.将字符串字符向前移动一个位置,即sp加1,进行下一次匹配,转到步骤1。直到返回True或False,如果返回True,直接返回;
如果返回False,则需要向前回溯,即当前遍历字符串后退1步,并且当前遍历的模式串字符向前前进2步(用来跳过当前这个'*'),
重新遍历,转到步骤1.
6.当前遍历的字符串字符和模式串字符均向前前进一步,转到步骤1,继续下一次遍历。
7.判断当前遍历的模式串字符的下一个字符是不是'*',如果是,转到步骤8;如果不是,返回false
8.当前遍历的模式串字符前进2步,跳过这个'*'(因为'*'代表0次或多次重复,这里跳过相当于0次重复),转到步骤1,继续下一次
遍历。
9.其他情况均返回false
3.代码实现
根据上面的思路分析,可以画出流程图,根据流程图写出代码,代码实现如下:
#include <bits/stdc++.h> //万能头文件
using namespace std;
bool solve(string s, string p, int sp, int pp){
if(pp == p.length()) //模式串是否遍历完,步骤1
return sp == s.length(); //根据字符串是否遍历完,返回true或false
if(sp == s.length()){ //字符串是否遍历完,步骤2
if(p[pp+1] == '*')
return solve(s, p, sp, pp+2);
else
return false;
}
if(s[sp] == p[pp] || p[pp] == '.'){ //两字符是否匹配,步骤3
if(p[pp+1] == '*'){ //模式串下一字符是否为'*',步骤4
if(solve(s, p, sp+1, pp)) //步骤5
return 1;
return solve(s, p, sp, pp+2); //回溯过程
else //步骤6
return solve(s, p, sp+1, pp+1);
}
else if(p[pp+1] == '*') //步骤7
return solve(s, p, sp, pp+2); //步骤8
return 0; //步骤9
}
bool isMatch(string s, string p){
return solve(s, p, 0, 0);
}