LeetCode:10. Regular Expression Matching
老大难问题,终于算是理解了。
首先状态定义不难写(哈哈):
dp[i][j]: s[0->i-1] p[0->j-1],它们是不是符合。
难的是状态转移方程(又一次验证):
1.如果s[i-1]== p[j-1] || p[j-1] == ‘.’, dp[i][j] = dp[i-1][j-1]
2.如果p[j-1] == '*'并且重复0次,那么dp[i][j] = dp[i][j-2]
3.如果p[j-1] == '*'并且重复至少一次,那么dp[i][j] = dp[i-1][j] && (s[i-1] == p[j-2] || p[j-2] == ‘.’)
比较难以理解的是3,这里尝试解释一下:
s: 0, 1, …, i-2, i-1
p: 0, 1, …, j-2, j-1
此时p[j-1]==’’,如果这个 * 重复至少一次,就说明1.s[i-1] == p[j-2] || p[j-2] == '.‘是需要的 2.看的是dp[i-1][j],而不是dp[i-1][j-1],因为如果只看dp[i-1][j-1]的话,那么就说明这个’'只重复了一次,但是这里需要包含不止一次的情况,所以要看dp[i-1][j]。而且dp[i-1][j]表示的是这个*重复了0 次或者多次,所以在加上这里的s[i-1],就表示1次或者更多。
class Solution {
public:
bool isMatch(string s, string p) {
int ssz = s.size(), psz = p.size();
vector<vector<bool>> dp(ssz+1, vector<bool>(psz+1, false));
dp[0][0] = true;
for (int j = 1; j <= psz; ++j)
if (p[j-1] == '*' && dp[0][j-2])
dp[0][j] = true;
for (int i = 1; i <= ssz; ++i)
for (int j = 1; j <= psz; ++j) {
if (p[j-1] == '*')
dp[i][j] = dp[i][j-2] || (dp[i-1][j] && (s[i-1] == p[j-2] || p[j-2] == '.'));
else
dp[i][j] = dp[i-1][j-1] && (s[i-1] == p[j-1] || p[j-1] == '.');
}
return dp.back().back();
}
};
另外这题比较坑爹的是题目没有说明不会出现一些边角情况:比如:
*不会出现在开头
*不会连续出现
容易导致想复杂了