LeetCode 10 : 正则表达式匹配

题目描述

Given an input string (s) and a pattern §, 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).
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 *.

给定一个字符串 (s) 和一个字符模式 §。实现支持 ‘.’ 和 ‘*’ 的正则表达式匹配。
‘.’ 匹配任意单个字符。
‘*’ 匹配零个或多个前面的元素。
匹配应该覆蓋整个字符串 (s) ,而不是部分字符串。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

解题思路

根据题意,给定两个假设:

  1. * 不能出现在开头
  2. 不能出现连续的*(两个或多个)

基于动态规划的解题思路:

matrix[i][j]表示s的前i个字符[0,i)组成的subString,与p的前j个字符[0,j)组成的subString的匹配结果,可以推断,matrix[i][j]可以由已知的状态推断出未知的状态

递推矩阵的初始化

矩阵的大小应该是matrix[len(s)][len§]

  1. matrix[0][0]表示s和都是null,可以匹配,返回True
  2. s为非null,p是null,永远不匹配,返回False
  3. s为null,p为非null时,需要分情况:如果没有*,则一定不能匹配;
    (注意:根据题意描述,我们推断: *不能是第一个字符,同时,两个以上*不能连续出现)
    如果是*,matrix[0][n]结果与matrix[0][n-2]结果相同
代码如下:
令matrix[i][j]表示s的前i个字符[0,i)组成的subString,与p的前j个字符[0,j)组成的subString的匹配结果
 '''
matrix = [[False for i in range(n+1)] for i in range(m+1)]
'''
1、s和p都是null时,可以匹配,返回True
'''
matrix[0][0]=True
'''
2、 s为非null,p是null,永远不匹配,返回False
3、 s为null,p为非null时,需要分情况:如果没有*,则一定不能匹配;
    (注意:根据题意描述,我推断: *不能是第一个字符,同时,两个以上*不能连续出现)
    如果是*,matrix[0][n]结果与matrix[0][n-2]结果相同
'''
for i in range(2,n+1):
    if(p[i-1] == '*'):                
         matrix[0][i] = matrix[0][i-2]

状态转移方程为:

  1. 如果s[i-1] == p[j-1] 或者 p[j-1] == “.” 则: matrix[i][j] = matrix[i-1][j-1]
  2. 如果p[j-1] == “*” 则分2种情况:
       1. 如果 p[j-2] == s[i-1]或者p[j-2]==”.”
       则 matrix[i][j] = {
        matrix[i][j-2] (此时表示前边的字符出现0次)
        or matrix[i][j-1] (此时*表示前边的字符出现1次)
        or matrix[i-1][j] (此时
    表示前边的字符出现多次)
       }
       2. 如果 p[j-2]不是”.”,也不是s[i-1]
       则 matrix[i][j] = matrix[i][j-2]

完整python代码

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m = len(s)
        n = len(p)
        '''
        初始化递推矩阵
        令matrix[i][j]表示s的前i个字符[0,i)组成的subString,与p的前j个字符[0,j)组成的subString的匹配结果
        '''
        matrix = [[False for i in range(n+1)] for i in range(m+1)]
        '''
        1、s和p都是null时,可以匹配,返回True
        '''
        matrix[0][0]=True
        '''
        2、 s为非null,p是null,永远不匹配,返回False
        3、 s为null,p为非null时,需要分情况:如果没有*,则一定不能匹配;
            (注意:根据题意描述,我推断: *不能是第一个字符,同时,两个以上*不能连续出现)
            如果是*,matrix[0][n]结果与matrix[0][n-2]结果相同
        '''
        for i in range(2,n+1):
            if(p[i-1] == '*'):                
                matrix[0][i] = matrix[0][i-2]
        '''
        状态转移公式:
        令matrix[i][j]表示s的前i个字符[0,i)组成的subString,与p的前j个字符[0,j)组成的subString是否匹配,则
        1、  如果s[i-1] == p[j-1] 或者 p[j-1] == "."   则: matrix[i][j] = matrix[i-1][j-1]
        2、  如果p[j-1] == "*" 则分2种情况: 
                1)如果 p[j-2] == s[i-1]或者p[j-2]=="." 
                  则 matrix[i][j] =( matrix[i][j-2](此时*表示前边的字符出现0次)  
                  or matrix[i][j-1](此时*表示前边的字符出现1次)
                  or matrix[i-1][j](此时*表示前边的字符出现多次)    )
                2)如果 p[j-2]不是".",也不是s[i-1]
                  则 matrix[i][j] = matrix[i][j-2]

        '''      
        for i in range(1, m+1):
            for j in range(1, n+1):
                if( p[j-1]=="." or s[i-1] == p[j-1] ):
                    matrix[i][j] = matrix[i-1][j-1]
                elif ( p[j-1] == "*" ):
                    if ( p[j-2]=="." or p[j-2]==s[i-1] ):
                        matrix[i][j] = ( matrix[i][j-1] or matrix[i][j-2] or matrix[i-1][j])
                    else :
                        matrix[i][j] = matrix[i][j-2]


        return matrix[m][n]
点赞