題目
Given an input string(s) and a pattern(p), 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 . or * .
Example1:
Input:s = "aa" p="a"
Output:false
Explanation:"a" does not match the entire string "a"
Example2:
Input:s = "aa" p="a*"
Output:true
Explanation:".*" means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it become "a".
Example3:
Input:s = "ab" p=".*"
Output:true
Explanation:"." means " zero or more () of any character (.) " .
思路
動態規划
Step1. 刻畫一個最優解的結構特征
\(dp[i][j]\)表示\(s[0,\cdots,i-1]\)與\(p[0,\cdots,j-1]\)是否匹配
Step2. 遞歸定義最優解的值
1.\(p[j-1] == s [i-1]\),則狀態保存,\(dp[i][j] = dp[i-1][j-1]\)
2.\(p[j-1] ==\) .
,.
與任意單個字符匹配,於是狀態保存,\(dp[i][j] = dp[i-1][j-1]\)
3.$p[j-1] == $*
,*
只能以X*
的形式才能匹配,但是由於*
究竟作為幾個字符匹配不確定,此時有兩種情況:
- \(p[j-2] != s[i-1]\),此時\(s[0,\cdots,i-1]\)與\(p[0,\cdots,j-3]\)匹配,即\(dp[i][j] = dp[i][j-2]\)
- \(p[j-2] == s[i-1]\) 或者 $p[j-2] == $
.
,此時應分為三種情況:
*
作為零個字符,\(dp[i][j] = dp[i][j-2]\)
*
作為一個字符,\(dp[i][j] = dp[i][j-1]\)
*
作為多個字符,\(dp[i][j] = dp[i-1][j]\)
Step3. 計算最優解的值
根據狀態轉移表,以及遞推公式,計算dp[i][j]
Tips
數組初始化(python)
(1)相同的值初始化(一維數組)
#方法一:list1 = [a a a ]
list1 = [ a for i in range(3)]
#方法二:
list1 = [a] * 3
(2)二維數組初始化
初始化一個\(4*3\)每項固定為0的數組
list2 = [ [0 for i in range(3)] for j in range(4)]
C++
class Solution {
public:
bool isMatch(string s, string p) {
int m = s.length(),n = p.length();
bool dp[m+1][n+1];
dp[0][0] = true;
//初始化第0行,除了[0][0]全為false,因為空串p只能匹配空串,其他都無能匹配
for (int i = 1; i <= m; i++)
dp[i][0] = false;
//初始化第0列,只有X*能匹配空串
for (int j = 1; j <= n; j++)
dp[0][j] = j > 1 && '*' == p[j - 1] && dp[0][j - 2];
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (p[j - 1] == '*')
{
dp[i][j] = dp[i][j - 2] || (s[i - 1] == p[j - 2] || p[j - 2] == '.') && dp[i - 1][j];
}
else //只有當前字符完全匹配,才能傳遞dp[i-1][j-1] 值
{
dp[i][j] = (p[j - 1] == '.' || s[i - 1] == p[j - 1]) && dp[i - 1][j - 1];
}
}
}
return dp[m][n];
}
};
Python
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
len_s = len(s)
len_p = len(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):
dp [0][i] = i>1 and dp[0][i - 2] and p[i-1] == '*'
for i in range (1, len_s + 1 ):
for j in range(1, len_p + 1):
if p[j - 1] == '*':
#狀態保留
dp[i][j] = dp[i][j -2] or (s[i-1] == p[j-2] or p[j-2] == '.') and dp[i-1][j]
else:
dp[i][j] = (p[j-1] == '.' or s[i-1] == p[j-1]) and dp[i-1][j-1]
return dp[len_s][len_p]