LeetCode - Regular Expression Matching

来源:互联网 发布:淘宝显示历史价格插件 编辑:程序博客网 时间:2024/04/30 07:44

LeetCode - Regular Expression Matching

The Problem is described as following:

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(“aa”, “.*”) → true
isMatch(“ab”, “.*”) → true
isMatch(“aab”, “c*a*b”) → true

整体来说,这道题目具有一定的难度,起初我采用的是递归的解法,但是python写的代码会存在LTE的问题(貌似C++和Java可以AC),遂放弃,转而研究DP的解法,一下对两种方法均做简单说明

递归方法:

针对p的长度分三种情况讨论:

  • len(p)==0时,当且仅当s长度为0输出True;
  • len(p)==1时,当且仅当s长度为1且字符相等(注意p[0]=’.’的情况),输出True;
  • len(p)>1时,需要根据p[1]是否为*,再作区分:
    • p[1]!=’*’ 时,这一情况较为简单,若s[0]!=p[0],输出False,否则字符去掉前一位继续比较;
    • p[1]==’*’,因为不确定星号以及其之前的元素出现次数,就需要针对s中到底有多少位被抵消,分别展开讨论,会带来较大的时间消耗,想必这也就是python代码AC不过的原因,
# Solution version 1# TLE when input:  "baccbbcbcacacbbc", "c*.*b*c*ba*b*b*.a*"class Solution:    # @param s, a string    # @param p, a string    # @return a boolean    def isMatch(self, s, p):        # len == 0        if len(p) == 0:            return len(s) == 0        # len == 1        if len(p) == 1:            return (len(s) == 1) and (s[0] == p[0] or p[0] == '.')        # len > 1 ,next char is '*'        if p[1] != '*':            if len(s) == 0:                return False            else:                return (s[0] == p[0] or p[0] == '.') and (self.isMatch(s[1:],p[1:]))        # next char is '*', more complicated        while (len(s) > 0) and (s[0] == p[0] or p[0] == '.'):            if self.isMatch(s, p[2:]):                return True            s = s[1:]        return self.isMatch(s,p[2:])

动态规划:

这一部分思路参考此博客:

思路是使用bool类型的二维数组dp[m+1][n+1](m、n分别为字符串s和p的长度)记录s和p是否匹配,即dp[i+1][j+1]表示s的前i个字符是否与p的前j的字符相匹配。

  • 如果p[j]不等于‘*‘,则dp[i + 1][j + 1] = dp[i][j] && s[i] == p[j]

  • 如果p[j]等于‘*‘,则当且仅当在下面三种情况为真,dp[i + 1][j + 1]为真:

    • ‘*‘前面字符重复出现0次,则p字符串需要往前看2位,即dp[i + 1][j - 1]是否为真

    • ‘*‘前面的字符重复出现1次,则p字符串只需要往前看1位,即dp[i + 1][j]是否为真

    • ‘前面的字符重复出现次数大于1次,则s字符串需要往前看1位,即dp[i][j + 1]是否为真,以及s字符串当前字符(s[i])与p字符串‘‘前面字符(p[j - 1])是否相匹配。

 # Solution Version 2 with DP . AC succeed .class Solution:    # @param s, a string    # @param p, a string    # @return a boolean    def isMatch(self, s, p):        dp = [[False for i in range(len(p)+1)] for j in range(len(s)+1)]        dp[0][0] = True        for i in range(1,len(p)+1):            if p[i-1] == '*' and i >= 2:                dp[0][i] = dp[0][i-2]        for i in range(1,len(s)+1):            for j in range(1,len(p)+1):                if p[j-1] == '.' or p[j-1] == s[i-1]:                    dp[i][j] = dp[i-1][j-1]                elif p[j-1] == '*':                    dp[i][j] = dp[i][j-2] or dp[i][j-1] or (dp[i-1][j] and (s[i-1] == p[j-2] or p[j-2] == '.'))        return dp[len(s)][len(p)]
0 0
原创粉丝点击