• LeetCode Wildcard Matching


    class Solution {
    public:
        bool isMatch(const char *s, const char *p) {
            if (s == NULL || p == NULL) return false;
            int slen = 0;
            int plen = 0;
            
            while (s[slen] != '') slen++;
            while (p[plen] != '') plen++;
            
            if (slen == 0 && plen == 0) return true;
            if (plen == 0) return false;
            
            int si = 0;
            int pi = 0;
            int ppi = -1;
            int psi = 0;
            
            while (si < slen) {
                if (s[si] == p[pi] || p[pi] == '?') {
                    si++, pi++;
                } else if (p[pi] == '*') {
                    ppi = pi++;
                    psi = si;
                } else if (ppi != -1){
                    pi = ppi + 1;
                    si = ++psi;
                } else {
                    return false;
                }
            }
    
            while (p[pi] == '*') pi++;
            return pi == plen;
        }
    };

     真写不出这样的代码。

    参考:http://www.cnblogs.com/zhuli19901106/p/3572736.html

    下面是自己写的记忆搜索代码,TLE了

    class Solution {
    private:
        char* memo;
        int slen;
        int plen;
    public:
        bool isMatch(const char *s, const char *p) {
            slen = strlen(s);
            plen = strlen(p);
            
            memo = new char [(slen+1) * (plen+1)];
            for (int i=(slen+1) * (plen+1) - 1; i>=0; i--) memo[i] = -1;
            bool ret = dfs(s, 0, p, 0);
            delete[] memo;
            return ret;
        }
        
        bool dfs(const char* s, int spos, const char* p, int ppos) {
            int idx = ppos * slen + spos;
            if (memo[idx] >= 0) return memo[idx];
            
            if (s[spos] == '' && p[ppos] == '') return true;
            if (p[ppos] == '') return false;
            if (s[spos] == '') {
                int i = ppos;
                for (; p[i] != ''; i++) {
                    if (p[i] != '*') break;
                }
                memo[idx] = p[i] == '';
                return memo[idx];
            }
            
            
            bool ret = false;
    
            if (p[ppos] == '?') {
                ret = dfs(s, spos + 1, p, ppos + 1);
            } else if (p[ppos] == '*') {
                for (int i=0; s[spos + i] != ''; i++) {
                    if (dfs(s, spos + i, p, ppos + 1)) {
                        ret = true;
                        break;
                    }
                }
            } else if (p[ppos] == s[spos]) {
                ret = dfs(s, spos + 1, p, ppos + 1);
            }
            memo[idx] = ret;
            return ret;
        }
    };

    第二轮:

    再理解一下,source字符串和pattern字符串,设有两个指针si, pi分别指向source和pattern,

    1. 如果遇到普通字符和?则依次匹配,即si++, pi++,如果此时发生失配且前面没有*出现,则此时已经无可奈何,匹配失败

    2. 如果遇到有*,则记录此时的si为psi,pi为ppi。如字符串:

        abcddde

        ab*d?

        前面的ab匹配完成时,在pattern中遇到*,*可以匹配任意长度的字符,即可以产生以下几种尝试:

        1. ab cddde <-----> ab d?   (忽略*,即*匹配零个字符,si = psi,       pi = ppi + 1)

        2. ab ddde <------> ab d?  (*代替一个c,                    si = psi + 1,  pi = ppi + 1)

        3. ab dde <-------> ab d? (*代替cd,                          si = psi + 2, pi = ppi + 1)

        4. ab de <--------> ab d? (*代替cdd,                        si = psi + 3,  pi = ppi + 1)

        ...

    由于我们记录了发现*时的索引,当我们在后续的尝试中失败时可以换另一种进行尝试。比如上述列表中1尝试失败时,可以立即尝试2中的情况,如此继续下去。 

    又默写了一遍,算题真是无奈。

    有写了一次还是不流畅,函数签名换了

     1 class Solution {
     2 public:
     3     bool isMatch(string s, string p) {
     4         int slen = s.size();
     5         int plen = p.size();
     6         s = s+"_";
     7         p = p+"_";
     8         int si = 0;
     9         int pi = 0;
    10         int wpi = -1;
    11         int wsi = -1;
    12         
    13         while (si < slen) {
    14             if (s[si] == p[pi] || p[pi] == '?') {
    15                 si++, pi++;
    16             } else if (p[pi] == '*') {
    17                 wsi = si;
    18                 wpi = pi++;
    19             } else if (wpi != -1) {
    20                 si = ++wsi;
    21                 pi = wpi + 1;
    22             } else {
    23                 return false;
    24             }
    25         }
    26         
    27         while (pi < plen) {
    28             if (p[pi++] != '*') {
    29                 return false;
    30             }
    31         }
    32         
    33         return true;
    34     }
    35 };

     再来,凡人只能勤加练习

    // 10:15
    // abcdef$
    // ab$
    class Solution {
    public:
        bool isMatch(string s, string p) {
            
            int slen = s.size();
            int plen = p.size();
            
            s.push_back('$');
            p.push_back('$');
            
            int si = 0;
            int pi = 0;
            
            int psi = -1;
            int ppi = -1;
            
            while (si < slen) {
                if (s[si] == p[pi] || p[pi] == '?') {
                    si++, pi++;
                } else if (p[pi] == '*') {
                    psi = si;
                    ppi = ++pi;
                } else if (psi != -1) {
                    si = ++psi;
                    pi = ppi;
                } else {
                    return false;
                }
            }
            
            while (pi < plen) {
                if (p[pi++] != '*') {
                    return false;
                }
            }
            return true;
        }
    };

    这里向末尾加入截止符可以避免一些边界上的处理,但必须是字符串中不会出现的,在C里面可以选择使用'',其实C++里也可以push_back进去,不过这样太奇葩。

  • 相关阅读:
    MySql常用命令
    PHP截断函数mb_substr()
    explode() 字符串转换数组
    php取得当前时间函数
    Apache与Nginx的比较
    thinkphp5.0环境变量配置
    thinkphp5.0配置作用域
    thinkphp5.0动态配置
    Mac 下查看 Android Studio 的 SHA1的方法
    Mac 下 gradle 路径
  • 原文地址:https://www.cnblogs.com/lailailai/p/3870794.html
Copyright © 2020-2023  润新知