一、Problem
給你一個字符串 s 和一個字符規律 p,請你來實現一個支持 ‘.’ 和 ‘*’ 的正則表達式匹配。
‘.’ 匹配任意單個字符
‘*’ 匹配零個或多個前面的那一個元素
所謂匹配,是要涵蓋 整個 字符串 s的,而不是部分字符串。
說明:
s 可能爲空,且只包含從 a-z 的小寫字母。
p 可能爲空,且只包含從 a-z 的小寫字母,以及字符 . 和 *。
輸入:
s = "aa"
p = "a"
輸出: false
解釋: "a" 無法匹配 "aa" 整個字符串。
輸入:
s = "aab"
p = "c*a*b"
輸出: true
解釋: 因爲 '*' 表示零個或多個,這裏 'c' 爲 0 個, 'a' 被重複一次。因此可以匹配字符串 "aab"。
二、Solution
方法一:dp
- 定義狀態:
- 表示 s 的前 個字符能否被 p 的前 個字符匹配
- 思考初始化:
- ,表示空串與空串可匹配
- 表示字符串 p 的前 個字符只有當 爲空串,且 爲 時纔可以匹配。
- 思考狀態轉移方程:注:
- 如果 則有 ,否則 —>
- 如果 ,此時的 * 號有兩種作用:
- 清空:有 ,即將字符串 p 的第 個字符清走,比如 (ab, abc*),就將字母 c 清走
- 補全:如果 即 (abbb,ab*),或者 (abbb,ab* / a.*)
- 思考輸出:
還是有點複雜的,如果沒有正則表達式基礎的同學可能會有點暈,可以放一放…
class Solution {
public boolean isMatch(String S, String P) {
char s[] = S.toCharArray(), p[] = P.toCharArray();
int n = s.length, m = p.length;
boolean f[][] = new boolean[n+1][m+1];
f[0][0] = true;
for (int j = 2; j <= m; j++)
f[0][j] = f[0][j-2] && p[j-1] == '*';
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (s[i-1] == p[j-1] || p[j-1] == '.') {
f[i][j] = f[i-1][j-1];
} else if (p[j-1] == '*') {
f[i][j] = f[i][j-2] || f[i-1][j] && (s[i-1] == p[j-2] || p[j-2] == '.');
}
}
return f[n][m];
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,