leetcode 44

思路:贪心

1.假设p格式为”*p1*p2*p3*“,其中pi代表一个被分割的子串,我们只需要在s当中找到相应子串便可匹配成功了。比如说s=“abcdefgabc”,p=“bcdfgb*”,那么我们只需要按pi的相对顺序到s当中找到相应子串即可匹配成功。
2.然而p也可能表示为”p0*p1*p2*p3*p4“,这样的话,我们得保证s当中必须以p0开头而且以p4结尾。
3.为了保证以p4结尾,我们从后开始遍历s和p,令i=s.size()-1,j=p.size()-1,如果s[i]p[j]或者p[j]’?’,则分别从s和p中弹出匹配的字符,直到找到p串当中最后一个‘*’,这样我们保证了p的格式为”p0*p1*p2*p3*“。
4.然后我们设置pStart=0,代表当前p正在匹配的子串pk的起始位置,sStart=-1,代表s正在与p子串pk匹配的起始位置,为什么sStart=-1呢?因为p的开始可能就是‘*’。
5.令i=0,j=0,开始从头匹配s和p

  • 如果p[j]==’*’,也就是找到了一个p子串 p k p_k pk,我们那么我们更新p下一个子串 p k + 1 p_{k+1} pk+1的匹配起始位置为j+1,将pStart更新为j+1,然后j=pStart;这时因为s[i]并没有与p的任何字符匹配所以,i不变,但是sStart需要更新为sStart。
  • 如果s[i]s[j]或者p[j]’?’,也就是两个字符匹配,i++,j++,比较下一对字符。
  • 如果此时s[i]和s[j]匹配不上,这时我们需要考虑当前匹配的子串 p k 是 否 为 p 0 p_{k}是否为p_0 pkp0
  • 当k==0时,如果p的起始不为‘*’,那么匹配将失败。
  • 当k!=0时,我们需要更新s当中子串开始匹配的位置,令sStart++,然后i=sStart,j=pStart,重新开始比较s[i]和p[j]。

代码:

class Solution {
public:
    bool isMatch(string s, string p) {
        int i=s.size()-1;
        int j=p.size()-1;
        for(;i>=0&&j>=0;i--,j--)
        {
            if(p[j]=='*')
            {
                break;
            }
            else if(s[i]!=p[j]&&p[j]!='?')
            {
                return false;
            }
            else
            {
                s.pop_back();
                p.pop_back();
            }
        }
        i=j=0;
        int sStart=-1;//当前s子串开始匹配位置,从-1开始是因为p的开始可能是*
        int pStart=0;//当前p子串开始匹配的位置
        if(p.empty())
            return s.empty();
        while(i<s.size()&&j<p.size())
        {
            if(p[j]=='*')
            {
                sStart=i;
                j++;
                pStart=j;
            }
            else if(s[i]==p[j]||p[j]=='?')
            {
                i++;
                j++;
            }
            else if(sStart!=-1)
            {
                sStart++;
                i=sStart;
                j=pStart;
            }
            else
            {
                return false;
            }
        }
        while(j<p.size())
        {
            if(p[j++]!='*')
                return false;
        }
        return true;
    }

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值