1.題目基本資訊
1.1.題目描述
給你一個字串 s 和一個字元規律 p,請你來實現一個支援 ‘.’ 和 ‘*’ 的正規表示式匹配。
- ‘.’ 匹配任意單個字元
- ‘*’ 匹配零個或多個前面的那一個元素
所謂匹配,是要涵蓋 整個 字串 s 的,而不是部分字串。
1.2.題目地址
https://leetcode.cn/problems/regular-expression-matching/description/
2.解題方法
2.1.解題思路
動態規劃
2.2.解題步驟
第一步,狀態定義;dp[i][j]為s的前i個字串和p的前j個字串是否匹配
第二步,狀態初始化。初始化當匹配字串為空時的匹配狀態(即j=0時的狀態),因為除了原字串為空時,dp[0][0]=True,其餘的情況下dp[x][0]=False,所以只需要初始化dp[0][0]=True即可
第三步,狀態轉移。當判斷前i個字元和前j個匹配字元是否匹配時,這裡先預先定義倆字元匹配為匹配字元為.或者匹配字元和原字元兩者相等。
- 如果最後一個匹配字元為號,並且倒數第二個匹配字元和原字串最後一個字元匹配,可以選擇讓匹配一次,去除當前s子串中匹配的部分,此時的狀態轉移為dp[i][j]=dp[i-1][j],當選擇讓*匹配0個,則去除匹配子串中的x*組合,此時狀態轉移為dp[i][j]=dp[i][j-2];
- 如果最後一個匹配字元為*,並且倒數第二個匹配字元和原字串最後一個字元不匹配,則只能選擇讓*匹配0次,此時dp[i][j]=dp[i][j-2];
- 如果最後一個匹配字元不為*號,並且該匹配字元與原字串中最後一個字元匹配,此時的轉移方程為dp[i][j]=dp[i-1][j-1];
- 如果最後一個匹配字元不為*號,並且該匹配字元與原字串最後一個字元不匹配,則當前的原字串和匹配字串一定無法匹配,即dp[i][j]=False。
經過遍歷,最終的dp[sLen][pLen]即為題解
3.解題程式碼
Python程式碼
class Solution:
def isMatch(self, s: str, p: str) -> bool:
sLen,pLen=len(s),len(p)
# 第一步,狀態定義;dp[i][j]為s的前i個字串和p的前j個字串是否匹配
dp=[[False]*(pLen+1) for i in range(sLen+1)]
# 第二步,狀態初始化。初始化當匹配字串為空時的匹配狀態(即j=0時的狀態),因為除了原字串為空時,dp[0][0]=True,其餘的情況下dp[x][0]=False,所以只需要初始化dp[0][0]=True即可
dp[0][0]=True # 兩個都是空字串時,匹配
# 第三步,狀態轉移。當判斷前i個字元和前j個匹配字元是否匹配時,這裡先預先定義倆字元匹配為匹配字元為.或者匹配字元和原字元兩者相等。如果最後一個匹配字元為*號,並且倒數第二個匹配字元和原字串最後一個字元匹配,可以選擇讓*匹配一次,去除當前s子串中匹配的部分,此時的狀態轉移為dp[i][j]=dp[i-1][j],當選擇讓*匹配0個,則去除匹配子串中的x*組合,此時狀態轉移為dp[i][j]=dp[i][j-2];如果最後一個匹配字元為*,並且倒數第二個匹配字元和原字串最後一個字元不匹配,則只能選擇讓*匹配0次,此時dp[i][j]=dp[i][j-2];如果最後一個匹配字元不為*號,並且該匹配字元與原字串中最後一個字元匹配,此時的轉移方程為dp[i][j]=dp[i-1][j-1];如果最後一個匹配字元不為*號,並且該匹配字元與原字串最後一個字元不匹配,則當前的原字串和匹配字串一定無法匹配,即dp[i][j]=False。經過遍歷,最終的dp[sLen][pLen]即為題解
# > 判斷s[i]字元和p的p[j]字元是否匹配
def match(i,j):
if i<0 or j<0:
return False
if p[j]==".":
return True
elif p[j]==s[i]:
return True
else:
return False
for i in range(sLen+1):
for j in range(1,pLen+1):
if p[j-1]!="*":
if match(i-1,j-1):
dp[i][j]=dp[i-1][j-1]
else:
dp[i][j]=False
else:
if match(i-1,j-2):
dp[i][j]=dp[i-1][j] or dp[i][j-2]
else:
dp[i][j]=dp[i][j-2]
# print(dp[sLen][pLen])
return dp[sLen][pLen]
C++程式碼
class Solution {
public:
bool match(int i,int j,string s,string p){
if(i<0 || j<0){
return false;
}
if(p[j]=='.'){
return true;
}else if(p[j]==s[i]){
return true;
}else{
return false;
}
}
bool isMatch(string s, string p) {
int sLen=s.size(),pLen=p.size();
vector<vector<bool>> dp(sLen+1,vector<bool>(pLen+1,false));
dp[0][0]=true;
for(int i=0;i<sLen+1;++i){
for(int j=1;j<pLen+1;++j){
if(p[j-1]!='*'){
if(match(i-1,j-1,s,p)){
dp[i][j]=dp[i-1][j-1];
}else{
dp[i][j]=false;
}
}else{
if(match(i-1,j-2,s,p)){
dp[i][j]=dp[i-1][j] || dp[i][j-2];
}else{
dp[i][j]=dp[i][j-2];
}
}
}
}
return dp[sLen][pLen];
}
};