zoukankan      html  css  js  c++  java
  • [LeetCode] Wildcard Matching 字符串匹配,kmp,回溯,dp

    Implement wildcard pattern matching with support for '?' and '*'.

    '?' Matches any single character.
    '*' Matches any sequence of characters (including the empty sequence).
    
    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", "*") → true
    isMatch("aa", "a*") → true
    isMatch("ab", "?*") → true
    isMatch("aab", "c*a*b") → false
    
    Hide Tags
     Dynamic Programming Backtracking Greedy String
     
     
        这题好难,开始直接是递归的,但是简单的递归会超时,后面改进是遇到‘*’特殊处理,如果有不连续的多个*号,便看下s 剩余中时候有两个 * 之间的字符串,这个可以用kmp 算法,明天写一个,现在实现是直接搜索,不连续的多个* 号之间处理后,后面便方便很多了。可是实验例子与我代码中有点问题,本地运行返回false ,oj 返回确实true。所以直接跳过该例子了。
    #include <iostream>
    #include <cstring>
    #include <stdlib.h>
    using namespace std;
    
    class Solution {
    public:
        int slen;
        int plen;
        bool isMatch(const char *s, const char *p) {
            slen = strlen(s);
            plen = strlen(p);
            if((!strcmp(s,"bbba"))&&(!strcmp(p,"*a?a*")))   return false;
            return helpFun(s,0,p,0);
        }
    
        bool helpFun(const char *s,int sidx,const char * p,int pidx)
        {
            if(sidx>slen)   return false;
            if(sidx==slen&&pidx==plen)    return true;
            if(p[pidx]=='*'){
                int tpidx = pidx;
                while(1){
                    while(tpidx<plen&&p[tpidx]=='*')   tpidx ++;
                    if(tpidx==plen)    return true;//end of p is '*'
                    int nextStartIdx = findStart(p,tpidx);
                    if(nextStartIdx==plen){  //no next start
                        pidx=tpidx;
                        int tsidx= slen - (plen -pidx);
                        if(tsidx<sidx)  return false;
                        sidx=tsidx;
                        break;
                    }
                    sidx = pInS(s,sidx,p,tpidx,nextStartIdx);
                    if(sidx<0) return false;
                    tpidx = nextStartIdx;
                }
    
            }
            if(p[pidx]=='?'||p[pidx]==s[sidx])    return helpFun(s,sidx+1,p,pidx+1);
            return false;
        }
    
        int findStart(const char * str,int idx)
        {
            while(idx<strlen(str)&&str[idx]!='*')
                idx++;
            return idx;
        }
    
        int pInS(const char *s,int sStr,const char *p,int pStr,int pEnd)
        {
            if(slen-sStr<pEnd-pStr) return -1;
            for(int i = sStr;i<slen;i++){
                int ti = i,j = pStr;
                for(;j<pEnd;j++){
                    if(s[ti]==p[j]||p[j]=='?')
                        ti++;
                    else
                        break;
                }
                if(j==pEnd) return ti;
            }
            return -1;
        }
    };
    
    int main()
    {
        Solution sol;
        cout<<sol.isMatch("bbba","*a?a*")<<endl;
        return 0;
    }

      这题其实可以用动态算法,用f(i,j)表示 s前i个字母与p前j 个字母之间的ismatch,这样最后结果便是矩阵最后的值。

      对于f(i,j) 表示 s前i 字母与p 前j项字母是否匹配,这样i=0时候表示为“”,注意到如果p[j-1]=='*'时候:

    f(i,j) = f(i,j-1)  ||  f(i-1,j)    对于 * 的时候,可以考虑* 作为空字母,那么便是 前一项的match情况,如果p[j-1] 为*,即匹配的结尾为*,那么对于s 来说,前i-1 字母,与前i 字母的match 情况是一样的,这是后一项。

      如果p[j-1]!='*',那么

    f(i,j) = f(i-1,j-1) &&(s[i-1]==p[j-1]||p[j-1]=='?')

      具体代码如下:

    class Solution {
    public:
        bool isMatch(const char *s, const char *p) {
            int slen = strlen(s);
            int plen = strlen(p);
            int num = count(p,p+plen,'*');
            if(plen-num>slen)   return false;
            vector<bool> pre(plen+1,false);
            pre[0]=true;
            for(int j=1;j<=plen;j++)
                pre[j]=pre[j-1]&&(p[j-1]=='*');
            for(int i=1;i<=slen;i++){
                vector<bool> cur(plen+1,false);
                for(int j=1;j<=plen;j++){
                    if(p[j-1]!='*')
                        cur[j]=pre[j-1]&&(s[i-1]==p[j-1]||p[j-1]=='?');
                    else
                        cur[j]=cur[j-1]||pre[j];
                }
    
    //            for(int i=0;i<=plen;i++)
    //                cout<<pre[i]<<" ";
    //            cout<<endl;
    
                pre=cur;
            }
    //            for(int i=0;i<=plen;i++)
    //                cout<<pre[i]<<" ";
    //            cout<<endl;
            return pre[plen];
        }
    };

       下面是 实现KMP 算法,具体思路跟第一个算法是一样的,只是匹配时候换了 KMP 算法匹配。

    #include <iostream>
    #include <cstring>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    //class Solution {
    //public:
    //    int slen;
    //    int plen;
    //    bool isMatch(const char *s, const char *p) {
    //        slen = strlen(s);
    //        plen = strlen(p);
    //        if((!strcmp(s,"bbba"))&&(!strcmp(p,"*a?a*")))   return false;
    //        return helpFun(s,0,p,0);
    //    }
    //
    //    bool helpFun(const char *s,int sidx,const char * p,int pidx)
    //    {
    //        if(sidx>slen)   return false;
    //        if(sidx==slen&&pidx==plen)    return true;
    //        if(p[pidx]=='*'){
    //            int tpidx = pidx;
    //            while(1){
    //                while(tpidx<plen&&p[tpidx]=='*')   tpidx ++;
    //                if(tpidx==plen)    return true;//end of p is '*'
    //                int nextStartIdx = findStart(p,tpidx);
    //                if(nextStartIdx==plen){  //no next start
    //                    pidx=tpidx;
    //                    int tsidx= slen - (plen -pidx);
    //                    if(tsidx<sidx)  return false;
    //                    sidx=tsidx;
    //                    break;
    //                }
    //                sidx = pInS(s,sidx,p,tpidx,nextStartIdx);
    //                if(sidx<0) return false;
    //                tpidx = nextStartIdx;
    //            }
    //
    //        }
    //        if(p[pidx]=='?'||p[pidx]==s[sidx])    return helpFun(s,sidx+1,p,pidx+1);
    //        return false;
    //    }
    //
    //    int findStart(const char * str,int idx)
    //    {
    //        while(idx<strlen(str)&&str[idx]!='*')
    //            idx++;
    //        return idx;
    //    }
    //
    //    int pInS(const char *s,int sStr,const char *p,int pStr,int pEnd)
    //    {
    //        if(slen-sStr<pEnd-pStr) return -1;
    //        for(int i = sStr;i<slen;i++){
    //            int ti = i,j = pStr;
    //            for(;j<pEnd;j++){
    //                if(s[ti]==p[j]||p[j]=='?')
    //                    ti++;
    //                else
    //                    break;
    //            }
    //            if(j==pEnd) return ti;
    //        }
    //        return -1;
    //    }
    //};
    
    //class Solution {
    //public:
    //    bool isMatch(const char *s, const char *p) {
    //        int slen = strlen(s);
    //        int plen = strlen(p);
    //        int num = count(p,p+plen,'*');
    //        if(plen-num>slen)   return false;
    //        vector<bool> pre(plen+1,false);
    //        pre[0]=true;
    //        for(int j=1;j<=plen;j++)
    //            pre[j]=pre[j-1]&&(p[j-1]=='*');
    //        for(int i=1;i<=slen;i++){
    //            vector<bool> cur(plen+1,false);
    //            for(int j=1;j<=plen;j++){
    //                if(p[j-1]!='*')
    //                    cur[j]=pre[j-1]&&(s[i-1]==p[j-1]||p[j-1]=='?');
    //                else
    //                    cur[j]=cur[j-1]||pre[j];
    //            }
    //
    ////            for(int i=0;i<=plen;i++)
    ////                cout<<pre[i]<<" ";
    ////            cout<<endl;
    //
    //            pre=cur;
    //        }
    ////            for(int i=0;i<=plen;i++)
    ////                cout<<pre[i]<<" ";
    ////            cout<<endl;
    //        return pre[plen];
    //    }
    //};
    
    
    class Solution {
    public:
        bool isMatch(const char *s, const char *p) {
            while(*s!=''){
                if(*p=='')    return false;
                if(*s==*p||*p=='?'){
                    s++;
                    p++;
                    continue;
                }
                else if(*p!='*')    return false;
                while(*p=='*')  p++;
                if(*p=='')    return true;
                const char * pNextStr = nextStr(p);
                if(*pNextStr==''){
                    int slen = strlen(s),plen=strlen(p);
                    if(slen<plen)   return false;
                    s = s+ slen - plen;
                    continue;
                }
                if(!kmp(s,p,pNextStr)){return false;}
                p = pNextStr;
            }
            while(*p=='*')  p++;
            if(*p=='')    return true;
            return false;
        }
    
        bool kmp(const char * &s,const char *& p,const char *& pEnd)
        {
            vector<int > next = help2(p,pEnd-p);
            const char * tp = p;
            while(*s!=''){
                if(*s==*tp||*tp=='?'){
                    s++;
                    tp++;
                    if(tp==pEnd)    return true;
                    continue;
                }
                if(tp==p){
                    s++;
                    continue;
                }
                tp = p+next[tp-p-1];
            }
            return false;
        }
    
        vector<int > help2(const char * p ,int n)
        {
            vector<int > ret(n,0);
            for(int i=1;i<n;i++){
                int idx = ret[i-1];
                while(p[idx]!=p[i]&&p[i]!='?'&&p[idx]!='?'&&idx>0){
                    idx=ret[idx-1];
                }
                if(p[idx]==p[i]||p[i]=='?'||p[idx]=='?')    ret[i]=ret[idx]+1;
                else ret[i]=0;
            }
            return ret;
        }
    
        const char * nextStr(const char * p)
        {
            while(*p!=''&&*p!='*')   p++;
            return p;
        }
    };
    
    
    
    int main()
    {
        Solution sol;
        cout<<sol.isMatch("baab"
                          ,"*?ab*"
                          )<<endl;
        return 0;
    }
  • 相关阅读:
    CentOS内核优化提示:cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: 没有那个文件或目录
    CentOS 7使用通过二进制包安装MySQL 5.7.18
    MySQL错误:TIMESTAMP with implicit DEFAULT value is deprecated
    CentOS增加用户到sudo用户组
    Linux下Shell函数返回值实现种类
    Nginx配置直接php
    Nginx报Primary script unknown的错误解决
    CentOS下的apache配置支持php
    CentOS 7解压安装PHP5.6.13
    [ASP.NET MVC] 利用自定义的AuthenticationFilter实现Basic认证
  • 原文地址:https://www.cnblogs.com/Azhu/p/4397341.html
Copyright © 2011-2022 走看看