算法十正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

说明:

    s 可能为空,且只包含从 a-z 的小写字母。
    p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

示例 3:

输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。

示例 4:

输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。

示例 5:

输入:
s = "mississippi"
p = "mis*is*p*."
输出: false

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/regular-expression-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

拿到这个问题,想了想,这个难度是困难,感觉也有点绕。分析了一下,感觉可以从头开始一个个字符串匹配,唯一要处理的是p的*和.,思路就是,如果匹配,s和p都跳到下一个,不匹配,就是出错了。

这样需要加上*,如果当前匹配,s下一个与当前一样,p下一个是*,那么也是合适的。但是这是出现一个问题,比如s=sssa p=s*ssa,这样我无法区分*到底要匹配到哪里。

所以想是否可以逆向匹配呢?结果分析了一下,还是没解决这个问题,比如s=sssa p=sss*a,还是没办法区分*到底匹配多少。

这时发现,一切原因都归于在*的前后又出现了相同的字符串,那么是不是可以先把p变换一下呢把s*ssa或者sss*a都变成s*a,就是把相同的合并。

这样写了测试代码,提交发现有问题,分析后,突然发现这里面最影响分析,最影响性能,并且把我的这个方法变成无效的规则['.' 匹配任意单个字符],这里有个组合[".*" 表示可匹配零个或多个('*')任意字符('.')],会导致回到了上面的问题到底我要匹配到哪?示例:

s=aaabcd p=a.*abcd

怎么办呢,看来只能在这种方式下穷举了。拿上面的举例,在匹配到.*的时候,就需要判断.*不匹配任何字符,匹配一个字符,匹配多个相同字符分别是否成功,成功,则这种匹配规则是对的。

我的解一,看到题解中,有一个有限状态机的解法,感觉挺好的,也很好理解,然后按照那个提示写了一个所谓的穷举法。就是把匹配规则字符p按照类似的有限状态机的模式生成一个序列,每个节点定义了当前的匹配字符和是否可以重复(匹配0次或无限多次)。

如果当前节点不是可重复的,直接判断,如果匹配直接跳到下一个节点,不匹配就直接返回false;如果当前节点是可重复的,直接跳到下一个节点,如果这条分支返回false,就匹配当前节点一次,以此循环。

struct CHECKNODE
{
    //当前字符
    char c;
    //是否可以循环匹配0-n次
    bool rep;
    //下一个字符节点
    CHECKNODE* pnext;
    CHECKNODE()
    {
        c = 0;
        rep = false;
        pnext = nullptr;
    }
};
bool checkm(const string& s, int sindex, CHECKNODE* pnow)
{
    if (sindex == s.size())
    {
        if (pnow == nullptr)
        {
            return true;
        }
        else
        {
            if (pnow->rep)
            {
                return checkm(s, sindex, pnow->pnext);
            }
            else
            {
                return false;
            }
        }
    }
    if (sindex < s.size() && pnow == nullptr)
    {
        return false;
    }
    if (pnow->rep)
    {
        if (!checkm(s, sindex, pnow->pnext))
        {
            if (pnow->c == s[sindex] || pnow->c == '.')
            {
                return checkm(s, sindex + 1, pnow);
            }
            else
            {
                return false;
            }
            
        }
        else
        {
            return true;
        }
    }
    else
    {
        if (pnow->c == s[sindex] || pnow->c == '.')
        {
            return checkm(s, sindex + 1, pnow->pnext);
        }
        else
        {
            return false;
        }
    }
    return false;
}
bool isMatch(string s, string p) {
    CHECKNODE* pheard = nullptr;
    CHECKNODE* pnow = nullptr;
    for (auto& iter : p)
    {
        if (pheard == nullptr)
        {
            pheard = new CHECKNODE();
            pnow = pheard;
            pnow->c = iter;
        }
        else
        {
            if (iter != '*')
            {
                pnow->pnext = new CHECKNODE();
                pnow = pnow->pnext;
                pnow->c = iter;
            }
            else
            {
                pnow->rep = true;
            }
        }
    }
    return checkm(s, 0, pheard);
}

猜你喜欢

转载自www.cnblogs.com/studywithallofyou/p/12084395.html