leetcode 10. Regular Expression Matching

字符串匹配问题;

1、用暴力的方法解决。

通过搜索的方式,将每一种可能都列出来;

a*或.*的时候,分三路:1、s中没有匹配到,p直接右移两位继续递归搜索;2、s中有匹配到一个a,s右移一位,p右移两位继续递归搜索;3、s中有匹配到一个,p继续用a*继续匹配s接下去的字符,则s右移一位,p不右移继续递归搜索。

 

只有a或者.的时候,s和p有匹配到,两个都右移一位递归搜索;

复制代码
bool Match(const string& s, int s_i, const string& p, int p_i) {
        while (p.length() < p_i && p[p_i] == '*')
            ++p_i;
        if (s.length() == s_i && p.length() == p_i)
            return true;
        else if (s.length() != s_i && p.length() == p_i)
            return false;

        if (p_i + 1 < p.length()) {
            if (p[p_i+1] == '*') {
                if (Match(s, s_i, p, p_i + 2))
                    return true;
                if (s.length() > s_i && (s[s_i] == p[p_i] || p[p_i] == '.')) {
                    if (Match(s, s_i+1, p, p_i + 2))
                        return true;
                    if (Match(s, s_i+1, p, p_i))
                        return true;
                }
            } else {
                if (s.length() > s_i && (s[s_i] == p[p_i] || p[p_i] == '.')) {
                    if (Match(s, s_i+1, p, p_i + 1))
                        return true;
                }
            }
        } else {
            if (s.length() > s_i && (s[s_i] == p[p_i] || p[p_i] == '.')) {
                if (Match(s, s_i+1, p, p_i + 1))
                    return true;
            }
        }
        
        return false;
    }
View Code
复制代码

 

通过搜索发现,当前的搜索结果跟之前字符的搜索结果是有关系的;

当p+1 == a*的时候;即可以匹配0~n个相同的数;所以当匹配0个的时候: f(s+1,p) = f(s,p); 当匹配n=1个的时候: f(s+1,p + 1) = f(s,p)  又因为a*也符合f(s+1,p+1) = f(s+1,p); 当匹配n>1个的时候,则f(s,p+1)是匹配的,那么也应该符合f(s+1,p+1) = f(s,p+1),假设aa 跟a*应该是匹配的;

                             所以f(s+1,p+1) = f(s+1, p) | f(s,p) | f(s,p+1)

 

当p+1 == a的时候,则只有 f(s+1,p+1) = f(s,p)

复制代码
    bool DP(const string& s, const string& p) {
        vector<bool> arr(s.length()+1, false);
        arr[0] = true;
        
        int p_i = 0;
        while (p_i < p.length()) {
            while (p_i < p.length() && p[p_i] == '*')
                ++p_i;
            
            if (p_i == p.length())
                break;
            
            if (p_i + 1 < p.length()) {
                if (p[p_i+1] == '*') {
                    bool cur = arr[0];
                    bool mid = cur;
                    for (int i = 0; i < s.length(); ++i) {
                        mid = cur;
                        cur = arr[i+1];
                        if (p[p_i] == s[i] || p[p_i] == '.') {
                            arr[i + 1] = mid | arr[i] | arr[i+1];
                        }
                    }
                    ++p_i;
                } else {
                    bool cur = arr[0];
                    for (int i = 0; i < s.length(); ++i) {
                        if (p[p_i] == s[i] || p[p_i] == '.') {
                            bool mid = cur;
                            cur = arr[i+1];
                            arr[i+1] = mid;
                        } else {
                            cur = arr[i+1];
                            arr[i+1] = false;
                        }
                    }
                    arr[0] = false;
                }
            } else {
                bool cur = arr[0];
                for (int i = 0; i < s.length(); ++i) {
                    if (p[p_i] == s[i] || p[p_i] == '.') {
                        bool mid = cur;
                        cur = arr[i+1];
                        arr[i+1] = mid;
                    } else {
                        cur = arr[i+1];
                        arr[i+1] = false;
                    }
                }
                arr[0] = false;
            }
            ++p_i;
//            for (int i = 0; i < arr.size(); ++i)
//                cout << arr[i] << " ";
//            cout << endl;
        }
        
        return arr[s.length()];
    }
View Code
复制代码

 在代码中看到有一个可以操作的比较巧妙的地方:

复制代码
原本的
                bool cur = arr[0];
                for (int i = 0; i < s.length(); ++i) {
                    if (p[p_i] == s[i] || p[p_i] == '.') {
                        bool mid = cur;
                        cur = arr[i+1];
                        arr[i+1] = mid;
                    } else {
                        cur = arr[i+1];
                        arr[i+1] = false;
                    }
                }

改进后的
                for (int i = s.length() - 1; i >= 0; --i) {
                    if (p[p_i] == s[i] || p[p_i] == '.') {
                        arr[i+1] = arr[i];
                    } else {
                        arr[i+1] = false;
                    }
                }
复制代码

通过逆序的方式可以不需要记住原先的值;

 

posted @   LCAC  阅读(119)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示