关于动态规划(Dynamic Programming)
动态规划的基本思想是将一个问题划分为若干个子问题,并且每一个子问题可以用同样的方式递归解决。动态规划与分治算法最大的区别是,动态规划划分的子问题之间不是相互独立的,即可以通过存储中间步骤结果的方法来加快程序的运行速度。
题目:正则表达式匹配
给定一个字符串 (s
) 和一个字符模式 (p
)。实现支持 '.'
和 '*'
的正则表达式匹配。
'.' 匹配任意单个字符。
'*' 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s
) ,而不是部分字符串。
说明:
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母,以及字符.
和*
。
定义dp(i,j):
使用dp算法计算,dp(i,j)可以表示为:
case1:
case2:
case3: iff p[j-1] == '*' and dp(0,j-2) == 1.(dp(0,1) = false)
如:s = "",此时p = "a*b",j = 2,dp(0,2) = true.
dp(0,3) = false,p[2] != '*'
case4: if p[j-1] != '*'
case5: if p[j-1] == '*'
,iff 满足以下条件之一即可:
;
;
如,s = "aab",p = "c*a*b",dp(1,1) = false,dp(1,2) = false,
dp(1,4) = true(s[0] = p[2],dp(0,4) = true),dp(2,4) = true(s[1] = p[2],dp(1,4) = true).
又如,s = "c",p = "c*a*",dp(1,2) = true,dp(1,4) = true(cause dp(1,2) = true).
详细的代码如下所示:
class Solution {
public:
bool isMatch(string s, string p) {
int len1 = s.size(), len2 = p.size();
vector<vector<bool> > dp(len1 + 1, vector<bool>(len2 + 1,0));
//case1
dp[0][0] = true;
//case2
for (int i = 1; i <= len1; i++)
dp[i][0] = false;
//case3
for (int j = 1; j <= len2; j++)
dp[0][j] = j > 1 && p[j-1] == '*' && dp[0][j-2]
for (int i = 1; i <= len1; i++)
for (int j = 1; j <= len2; j++) {
//case4
if (p[j-1] != '*')
dp[i][j] = (s[i-1] == p[j-1] || p[j-1] == '.') && dp[i-1][j-1];
//case5
else {
dp[i][j] = dp[i][j-2] || (s[i-1] == p[j-2] || p[j-2] == '.') && dp[i-1][j];
}
}
return dp[len1][len2];
}
};