如何优化我的回溯解决方案以匹配正则表达式?

Posted

技术标签:

【中文标题】如何优化我的回溯解决方案以匹配正则表达式?【英文标题】:How do I optimize my backtracking solution for matching regexes? 【发布时间】:2018-11-17 04:29:46 【问题描述】:

这是我试图在 LeetCode 上解决的一个问题:

Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).
The matching should cover the entire input string (not partial).

Note:

s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like ? or *

我已经为这个问题想出了一个回溯解决方案,就像这样,

class Solution 

    public boolean isMatch(String s, String p) 
        p = p.replaceAll("\\*+", "*");

        return myIsMatch(s, p);
    

    public boolean myIsMatch(String s, String p) 
        if(s==null || p == null)
            return false;
        

        if(p.equals("*"))
            return true;
        


        int i = 0;
        while(i<s.length() && i<p.length() && s.charAt(i)==(p.charAt(i)))
            i++;

            if(i<s.length() && i>=p.length())
                return false;
            
        

        if(i == s.length() && i == p.length())
            return true;
        else if(i != s.length() && i == p.length())
            return false;
        else if(i == s.length() && i != p.length())
            if(p.charAt(i) == '*')
                return myIsMatch("", p.substring(i+1));    
            else
                return false;
            

        

        if(p.charAt(i)=='?')
            if(i+1<s.length() && i+1<p.length())
                return myIsMatch(s.substring(i+1), p.substring(i+1));    
            else if(i+1<s.length() && i+1>=p.length())
                return false;
            else if(i+1>=s.length() && i+1<p.length())
                return myIsMatch(s.substring(i+1), p.substring(i+1));
            else
                return true;
            
        else if(p.charAt(i)=='*')
            for(int k = i;k<=s.length();k++)
                if(myIsMatch(s.substring(k), p.substring(i+1)))
                    return true;
                
            
        else
            return false;
        
        return false;
    

这适用于大多数测试用例,除了以下病态的测试用例,程序似乎没有退出,

s = "abbabaaabbabbaababbabbbbbabbbabbbabaaaaababababbbabababaabbababaabbbbbbaaaabababbbaabbbbaabbbbababababbaabbaababaabbbababababbbbaaabbbbbabaaaabbababbbbaababaabbababbbbbababbbabaaaaaaaabbbbbaabaaababaaaabb"

p ="**aa*****ba*a*bb**aa*ab****a*aaaaaa***a*aaaa**bbabb*b*b**aaaaaaaaa*a********ba*bbb***a*ba*bb*bb**a*b*bb"

如何优化代码以处理此类输入?非常感谢任何帮助!

【问题讨论】:

【参考方案1】:

我认为程序不会退出。您的问题特别是您的算法对于您提供的输入运行速度不够快,并且您的时间用完了。

回溯解决方案不是匹配正则表达式的最佳方法。我认为您当前的算法具有 O(N^2) 的时间复杂度,但它可能会好得多,也许使用 动态编程 解决方案。我建议你重新考虑你的方法。

实际上,现在我想最好的解决方案确实是 O(mn)。

编辑:问题在于,除了会导致 O(mn) 时间复杂度的回溯解决方案之外,您还要遍历辅助函数中的字符串,使其类似于 O(n^3)。与其直接修改输入字符串,不如尝试使用 memoization 来解决问题。

【讨论】:

以上是关于如何优化我的回溯解决方案以匹配正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章

如何彻底避免正则表达式的灾难性回溯?

正则表达式匹配回溯

正则表达式回溯法原理

第977期正则表达式回溯法原理

如何使这个正则表达式不会导致“灾难性回溯”?

正则表达式 之 回溯引用:前后一致匹配