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] != '\0') slen++;

        while (p[plen] != '\0') 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] == '\0' && p[ppos] == '\0') return true;

        if (p[ppos] == '\0') return false;

        if (s[spos] == '\0') {

            int i = ppos;

            for (; p[i] != '\0'; i++) {

                if (p[i] != '*') break;

            }

            memo[idx] = p[i] == '\0';

            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] != '\0'; 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里面可以选择使用'\0',其实C++里也可以push_back进去,不过这样太奇葩。

你可能感兴趣的:(LeetCode)