題目詳情
給你一個字符串 s 和一個字符規律 p,請你來實現一個支持 '.' 和 '*' 的正則表達式匹配。
'.' 匹配任意單個字符
'*' 匹配零個或多個前面的那一個元素
所謂匹配,是要涵蓋 整個 字符串 s的,而不是部分字符串。
說明:
- s 可能爲空,且只包含從 a-z 的小寫字母。
- p 可能爲空,且只包含從 a-z 的小寫字母,以及字符 . 和 *。
示例 1:
輸入:
s = "aa"
p = "a"
輸出: false
解釋: "a" 無法匹配 "aa" 整個字符串。
示例 2:
輸入:
s = "aa"
p = "a*"
輸出: true
解釋: 因爲 '*' 代表可以匹配零個或多個前面的那一個元素, 在這裏前面的元素就是 'a'。因此,字符串 "aa" 可被視爲 'a' 重複了一次。
示例 3:
輸入:
s = "ab"
p = ".*"
輸出: true
解釋: ".*" 表示可匹配零個或多個('*')任意字符('.')。
示例 4:
輸入:
s = "aab"
p = "c*a*b"
輸出: true
解釋: 因爲 '*' 表示零個或多個,這裏 'c' 爲 0 個, 'a' 被重複一次。因此可以匹配字符串 "aab"。
示例 5:
輸入:
s = "mississippi"
p = "mis*is*p*."
輸出: false
——題目難度:困難
要解這道力扣困難題,即使是參考大神們的代碼思路 也得想半天呀...
不過也學到了很多,發現這道題目可以用動態規劃來解題,比較核心的點爲:用 dp[i][j] 表示 s 的前 i 個是否能被 p 的前 j 個匹配,然後圍繞此dp數組解題即可。
-下面解題代碼
class Solution {
public:
bool isMatch(string s, string p) {
int sLen = s.size();
int pLen = p.size();
if (pLen == 0) {
return sLen == 0? true : false;
}
vector<bool> tmp(pLen + 1, false);
vector<vector<bool>> dp(sLen +1, tmp); //dp[i][j] 表示 s 的前 i 個是否能被 p 的前 j 個匹配
dp[0][0] = true; //s 的前 0 個 肯定可以被 p 的前 0 個匹配
if (sLen != 0 && (p[0] == s[0] || p[0] == '.')) {
dp[1][1] = true;
}
//初始化情況:s爲空,p爲 .*.* 的情況
//也爲下面的遍歷匹配做準備工作
for(int i=1; i < pLen; i++)
{
if(p[i] == '*' && dp[0][i - 1]) {
dp[0][i + 1] = true;
}
}
for(int i=0; i < sLen; i++)
{
for(int j=1; j < pLen; j++)
{
/*p[j]不爲'*'的情況*/
if (p[j] == s[i] || p[j] == '.') {
dp[i + 1][j + 1] = dp[i][j];
}
/*p[j]爲'*'的情況*/
if(p[j] == '*') {
if (p[j - 1] == s[i] || p[j - 1] == '.') { //如果前一個元素匹配 或者 爲任意元素
dp[i + 1][j + 1] = (dp[i + 1][j - 1] || dp[i][j + 1]);
//看 dp[i + 1][j - 1]的情況:也就是 將當前組合(.*)扔掉,看 dp[i + 1][j - 1] 的情況
} else { //如果前一個元素不匹配 且不爲任意元素
dp[i + 1][j + 1] = dp[i + 1][j - 1]; //如果前一個元素不匹配,只能 將該組合(.*)扔掉 來看情況
}
}
}
}
return dp[sLen][pLen];
}
};
結果