力扣第十题题解 力扣第十题题解

力扣第十题题解

思路

问题描述就不写了,直接放地址leecode

第一个问题

很简单的想法就是使用双指针,但是双指针存在问题比如这个用例

aaa a*a

第一个a* 会尽可能多的匹配,然后就把aaa匹配完了。

正确的应该是a* 匹配两个a,既然如此,就用递归,每一种情况都确保考虑到,匹配零个,匹配一个,匹配两个...一直匹配到无法继续找到能和当前pattern 匹配的字符。

第二个问题

存在a*.* 的特殊形式,这种时候但看a. 是没有意义的,干脆把a* 变成A.*变成:,因为通过题目描述可知只有小写字母,句号和星号。

如果题目改变,pattern 含有的信息增多,比如增加了?,就需要使用更多的变换方式,或者使用面向对象(当前不用考虑)。

第三个问题

有一步没有添加字符串索引判断,导致异常,力扣使用的是AddressSanitizer判断的,但是错误页面含有的信息很少,只好自己再电脑上测试,但是这个不支持Windows ,只好使用Linux子系统测试。

g++ -fsanitize=address -std=c++11 xxx.cpp -o xxx

显示出了错误信息,但是没有行数,像这样

10_back+0x482c

这种的有点看不懂,将命令改为

g++ -fsanitize=address -std=c++11 xxx.cpp -g -o xxx,添加了-g。还有一个参数,-fno-omit-frame-pointer,想要了解更多,可以看这个Optimize-Options(当前不用了解)。

xxx.cpp:47

代码

增加了一个缓存,存储已经匹配过的数据。

cache[i][j]代表的是pattern.substr(j) 是否能够匹配str.substr(i)。

初始化为u,如果能够匹配改为y,如果不能匹配,改为为n


class Solution {
public:
    vector<vector<char>> *cache = nullptr;

    bool isMatch(string str, string pattern) {
        vector<char> newPattern;
        delete cache;
        cache = new vector<vector<char>>();
        for (int i = 0; i < pattern.length(); i++) {
            char current = pattern[i];
            char c = current;
            if (i < pattern.length() - 1) {
                char next = pattern[i + 1];
                if (next == '*') {
                    if (current == '.') {
                        c = ':';
                    } else {
                        c = (char) (current - 32);
                    }
                    i++;
                }
            }
            newPattern.push_back(c);
        }

        for (int i = 0; i < str.length(); i++) {
            vector<char> v;
            v.reserve(newPattern.size());
            for (int j = 0; j < newPattern.size(); ++j) {
                v.push_back('u');
            }
            cache->push_back(v);
        }
        bool result = toNextMatch(str, newPattern, 0, 0);
        return result;
    }

    bool toNextMatch(string &str, vector<char> &pattern, int str_pointer, int pat_pointer) {
        if (str_pointer < str.length() && pat_pointer < pattern.size())
            if (cache->at(str_pointer)[pat_pointer] != 'u') {
                //cout<<str.substr(str_pointer,str.length()-1)<<" "<<pat_pointer<<" 直接返回结果"<<endl;
                return cache->at(str_pointer)[pat_pointer] == 'y';
            }

        //cout<<"toNextMatch method called "<<str.length()<<" "<<str_pointer<<" "<<pattern.size()<<" "<<pat_pointer<<endl;
        if (pat_pointer == pattern.size()) {
            return str_pointer == str.length(); //检查pattern 是否消耗完了,如果没有消耗完,代表不匹配
        }
        char pattern_current = pattern[pat_pointer];
        if (pattern_current == ':' || isBigger(pattern_current)) {
            //复杂字符,可能匹配多个,也可能一个不匹配
            bool zero_match = toNextMatch(str, pattern, str_pointer, pat_pointer + 1); //一个也没有匹配
            if (str_pointer < str.length() && pat_pointer + 1 < pattern.size())
                cache->at(str_pointer)[pat_pointer + 1] = (zero_match ? 'y' : 'n');
            if (zero_match) {
                return true; //我一个也不匹配,后面的pattern 告诉我成功了,那我还能什么,直接返回成功
            }                //如果失败了,也不要气馁,继续匹配


            int start = str_pointer;
            while (start < str.length()) {
                //cout<<"offset "<<(start-str_pointer+1)<<endl;
                if (match(str[start], pattern_current)) { //匹配成功,并且打算就匹配到这个位置,后面的数据,尝试让后面的pattern 去匹配
                    int offset = str_pointer + start - str_pointer + 1;
                    bool unknown = toNextMatch(str, pattern, offset, pat_pointer + 1);
                    if (offset < str.length() && pat_pointer + 1 < pattern.size())

                        cache->at(offset)[pat_pointer + 1] = unknown ? 'y' : 'n';
                    if (unknown) {
                        //cout<<"return true"<<endl;
                        return true;
                    } //虽然失败了,也不要气馁,后面还有机会,坚持就是胜利
                } else {
                    //尽可能地匹配都没有一个可以成功的,最终也会失败,等着从while 出去再返回false,因为存在str匹配完了的问题
                    break;
                }
                start++;
            }
            return false; //毁灭吧,我累了
        } else {
            if (str_pointer >= str.length()) {
                return false;
            }

            //普通字符,匹配一个,就结束
            if (match(str[str_pointer], pattern_current)) {
                //cout<<"next"<<endl;
                return toNextMatch(str, pattern, str_pointer + 1, pat_pointer + 1); //匹配成功,继续向下匹配
            } else {
                return false; //匹配失败,不需要继续进行下去了
            }
        }
    }

    static bool isBigger(char c) {
        return c >= 'A' && c <= 'Z';
    }

    static bool match(char _s, char _p) {
        //cout<<"match called "<<_s<<"-"<<_p<<endl;
        if (isBigger(_p)) {
            return _s - _p == 32;
        } else if (_p == ':') {
            return true;
        } else if (_p == '.') {
            return true;
        } else {
            return _s == _p;
        }
    }
    ~Solution(){
        delete cache;//析构函数,否则会内存泄漏,AddressSanitizer挺好用
    }
};

其他的解题思路

动态规划,有限状态机

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章