给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:
s = "aa"
p = "*"
输出: true
解释: '*' 可以匹配任意字符串。
示例 3:
输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
示例 4:
输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".
示例 5:
输入:
s = "acdcb"
p = "a*c?b"
输出: false
#include<iostream> #include<stack> #include<algorithm> #include<string> #include<vector> using namespace std; /* 对于星号的处理,可以匹配任意字符串,简直像开了挂一样, 就是说在星号对应位置之前,不管你s中有任何字符串, 我大星号都能匹配你,那就是一旦p中有s中不存在的字符, 那么一定无法匹配,因为星号只能增加字符,不能消除字符, 再有就是星号一旦确定了要匹配的字符串, 对于星号位置后面的匹配情况也就鞭长莫及了。 所以p串中星号的位置很重要,用 jStart 来表示, 还有星号匹配到s串中的位置,使用 iStart 来表示, 这里 iStart 和 jStart 均初始化为 -1,表示默认情况下是没有星号的。 然后再用两个变量i和j分别指向当前s串和p串中遍历到的位置。 开始进行匹配,若i小于s串的长度,进行 while 循环。 若当前两个字符相等,或着p中的字符是问号, 则i和j分别加1。若 p[j] 是星号,要记录星号的位置, jStar 赋为j,此时j再自增1,iStar 赋为i。 若当前 p[j] 不是星号,并且不能跟 p[i] 匹配上, 此时就要靠星号了,若之前星号没出现过, 那么就直接跪,比如 s = "aa" 和 p = "c*", 此时 s[0] 和 p[0] 无法匹配,虽然 p[1] 是星号, 但还是跪。如果星号之前出现过,可以强行续一波命, 比如 s = "aa" 和 p = "*c",当发现 s[1] 和 p[1] 无法匹配时, 但是好在之前 p[0] 出现了星号,把 s[1] 交给 p[0] 的星号去匹配。 至于如何知道之前有没有星号,这时就能看出 iStar 的作用了, 因为其初始化为 -1,而遇到星号时,其就会被更新为i, 只要检测 iStar 的值,就能知道是否可以使用星号续命。 虽然成功续了命,匹配完了s中的所有字符,但是之后还要检查p串, 此时没匹配完的p串里只能剩星号,不能有其他的字符,将连续的星号过滤掉, 如果j不等于p的长度,则返回 false */ class Solution { public: bool isMatch(string s, string p) { int i = 0, j = 0, iStart = -1, jStart = -1, m = s.size(), n = p.size(); while (i < m) { if (j < n && (s[i] == p[j] || p[j] == '?')) { ++i; ++j; } else if (j < n && p[j] == '*') { iStart = i; jStart = j++; } else if (iStart >= 0) { i = ++iStart; j = jStart + 1; } else { return false; } } while (j < n && p[j] == '*') { ++j; } return j == n; } }; int main() { string s1; string s2; bool ans; getline(cin, s1); getline(cin, s2); ans = Solution().isMatch(s1, s2); cout << ans << endl; system("pause"); return 0; }