python %通配符 python带通配符的字符串匹配_字符串


题目

给定一个字符串 (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通过次数45,910提交次数148,304

解题代码与测试

Created by tannzh on 2020/7/7.///* * 给定一个字符串 (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通过次数45,910提交次数148,304 */#include #include using std::string;class Solution {public:    bool isMatch(string s, string p) {        int i = 0, j = 0, iStar = -1, jStar = -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] == '*') {                iStar = i;                jStar = j++;            } else if (iStar >= 0) {                i = ++iStar;                j = jStar + 1;            } else return false;        }        while (j < n && p[j] == '*') ++j;        return j == n;    }};int main(int argc, char **argv){    std::string s1 = "aa";    std::string p1 = "a";    std::string s2 = "aa";    std::string p2 = "*";    std::string s3 = "cb";    std::string p3 = "?a";    std::string s4 = "adceb";    std::string p4 = "*a*b";    std::string s5 = "acdcb";    std::string p5 = "a*c?b";    Solution s;    std::cout << s.isMatch(s1, p1) << std::endl;    std::cout << s.isMatch(s2, p2) << std::endl;    std::cout << s.isMatch(s3, p3) << std::endl;    std::cout << s.isMatch(s4, p4) << std::endl;    std::cout << s.isMatch(s5, p5) << std::endl;    return 0;}

解题思路分析

这道题通配符外卡匹配问题还是小有难度的,有特殊字符 ‘’ 和 ‘?’,其中 ‘?’ 能代替任何字符,‘’ 能代替任何字符串。两道题的星号的作用是不同的,注意对比区分一下。这道题最大的难点,就是对于星号的处理,可以匹配任意字符串,简直像开了挂一样,就是说在星号对应位置之前,不管你s中有任何字符串,我大星号都能匹配你,主角光环啊。但即便叼如斯的星号,也有其处理不了的问题,那就是一旦p中有s中不存在的字符,那么一定无法匹配,因为星号只能增加字符,不能消除字符,再有就是星号一旦确定了要匹配的字符串,对于星号位置后面的匹配情况也就鞭长莫及了。所以p串中星号的位置很重要,用 jStar 来表示,还有星号匹配到s串中的位置,使用 iStart 来表示,这里 iStar 和 jStar 均初始化为 -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。