• 蜗牛慢慢爬 LeetCode 10. Regular Expression Matching [Difficulty: Hard]


    题目

    Implement regular expression matching with support for '.' and '*'.

    '.' Matches any single character.
    '*' Matches zero or more of the preceding element.
    
    The matching should cover the entire input string (not partial).
    
    The function prototype should be:
    bool isMatch(const char *s, const char *p)
    
    Some examples:
    isMatch("aa","a") → false
    isMatch("aa","aa") → true
    isMatch("aaa","aa") → false
    isMatch("aa", "a*") → true
    isMatch("aa", ".*") → true
    isMatch("ab", ".*") → true
    isMatch("aab", "c*a*b") → true
    

    翻译

    实现正则表达式中的 .* 匹配

    Hints

    Related Topics: String, Dynamic Programming, Backtracking

    • 第一个方法就是比较暴力的BF:

      • 比较字符串 s 和 p 的 从 i 和 j 开始的子串是否匹配,用递归的方法直到串的最后,最后回溯得到结果
      • 那么假设现在走到了 s 的 i 位置和 p 的 j 位置:
        • p[j+1]不是 '*',那么判断 s[i] 和 p[j] 是否相同(注意 '.')不同返回 false,相同继续递归下一层 i+1,j+1
        • p[j+1]是 '*',那么看 s[i] 开始的子串,如果 s[i],s[i+1] ... s[i+k] 都等于 p[j],那么它们都可能是合适的匹配,这样递归就要尝试剩下的 (i,j+2),(i+1,j+2),(i+k,j+2)
    • 另一个方法就是动态规划:

      • 通过 dp[len(s)+1][len(p)+1]来存储计算过的结果
      • 遍历的话可以以 p 为外循环,也可以以 s 为外循环
      if p[j] == s[j]:  dp[i][j]=dp[i-1][j-1]
      if p[j] == '.':   dp[i][j]=dp[i-1][j-1]
      if p[j] == '*':  
          if p[j-1] != s[i]:  dp[i][j]=dp[i][j-2] //a*匹配空
          if p[j-1] == s[i] or p[j-1] == '.':
              dp[i][j] = dp[i][j-1] or    //a*匹配一个a
              dp[i][j] = dp[i][j-2] or    //a*匹配空
              dp[i][j] = dp[i-1][j]       //a*匹配两个a
      

    代码

    Java

    class Solution {
        public boolean isMatch(String s, String p) {
            if(s.length()==0 && p.length()==0){
                return true;
            }
            if(p.length()==0){
                return false;
            }
            boolean dp[][] = new boolean[s.length()+1][p.length()+1];
            dp[0][0] = true;
            for(int i=0;i<p.length();i++){
                if(p.charAt(i)=='*' && i>0 && dp[0][i-1])
                    dp[0][i+1] = true;
            }
            for(int i=0;i<s.length();i++){
                for(int j=0;j<p.length();j++){
                    if(p.charAt(j)=='.')
                        dp[i+1][j+1] = dp[i][j];
                    if(p.charAt(j)==s.charAt(i))
                        dp[i+1][j+1] = dp[i][j];
                    if(p.charAt(j)=='*'){
                        if(p.charAt(j-1)!=s.charAt(i) && p.charAt(j-1)!='.'){
                            dp[i+1][j+1] = dp[i+1][j-1];
                        }else{
                            dp[i+1][j+1] = (dp[i+1][j]||dp[i+1][j-1]||dp[i][j+1]);
                        }
                    }
                }
            }
            return dp[s.length()][p.length()];
        }
    }
    

    Python

    class Solution(object):
        def helper(self, s, p, i, j):
            if j == len(p):
                return i==len(s)
            if j == len(p)-1 or p[j+1]!='*':
                if i==len(s) or (s[i]!=p[j] and p[j]!='.'):
                    return False
                else:
                    return self.helper(s,p,i+1,j+1)
            while i<len(s) and (p[j]=='.' or s[i]==p[j]):
                if self.helper(s,p,i,j+2):
                    return True
                i += 1
            return self.helper(s,p,i,j+2)
        
        def isMatch(self, s, p):
            return self.helper(s,p,0,0)
    
    
  • 相关阅读:
    XML操作类
    输入框样式总结
    根据计算机MAC地址限定每台机子只能领取一次账号
    ico图标的应用
    C#实现关机功能
    在sql中实现数组
    JSON
    MvcHtml.ActionLink()用法
    Brettle.Web.NeatUpload.dll 大文件上传
    asp.net 创建Access数据库
  • 原文地址:https://www.cnblogs.com/cookielbsc/p/7498748.html
Copyright © 2020-2023  润新知