从上到下的动态规划,并且配合备忘录进行剪枝操作。
class Solution {
public:
//dp[i][j]表示 t的前j个元素构成的字符串 在 s的前i个元素构成的字符串 中出现的个数
vector<vector<int>> dp;
int numDistinct(string s, string t) {
//方法一:dfs超出时间限制
// int n = s.length(), m = t.length();
// if (m == 0)
// return 1;
// if (n < m)
// return 0;
// vector<int> path;
// vector<vector<int>> res;
// dfs(s,t,0,path,res);
// return res.size();
//方法二:处理后的 dfs,仍然是超时的
// int n = s.length(), m = t.length();
// if (m == 0)
// return 1;
// if (n < m)
// return 0;
// int count = 0;
// vector<vector<int>> cnt(64);
// for (int i=0;i<n;++i)
// cnt[s[i]-'A'].push_back(i);
// vector<int> path;
// vector<vector<int>> res;
// dfs2(cnt,t,path,res);
// return res.size();
//方法三:从上到下(将大问题转化为小问题的递归求解)的动态规划
int n = s.length(), m = t.length();
if (n < m)
return 0;
else if (n == m)
return s==t ? 1 : 0;
if (m == 0)
return 1;
if (dp.empty())
dp.assign(n+1, vector<int>(m+1, -1));
if (-1 != dp[n][m])
return dp[n][m];
//从后向前在“源串”中查找第一个等于“模式串”最后一个字符的索引
for (int j=n-1;j>=0;--j)
{
if (s[j] != t[m-1])
continue;
// dp[i][j]表示 t的前j个元素构成的字符串 在 s的前i个元素构成的字符串 中出现的个数
//状态转移方程:当 s[n-1] == t[m-1] 时,dp[n][m] = dp[n-1][m-1] + dp[n-1][m]
dp[n][m] = numDistinct(s.substr(0,j), t.substr(0,m-1)) + numDistinct(s.substr(0,j), t);
break;
}
// dp[n][m] = -1,说明上面的for循环没有执行到 dp[n][m] = numDistinct(s.substr(0,j), t.substr(0,m-1)) + numDistinct(s.substr(0,j), t);
// 就说明此时 “t的前j个元素构成的字符串 在 s的前i个元素构成的字符串 中出现的个数为0”
dp[n][m] = (dp[n][m] == -1 ? 0 : dp[n][m]);
return dp[n][m];
}
void dfs(const string& s, const string& t, int sIndex, vector<int>& path, vector<vector<int>>& res)
{
if (path.size() == t.length())
{
res.emplace_back(path);
return;
}
if (sIndex == s.length())
return;
for (int i=sIndex;i<s.size();++i)
{
if (s[i] == t[path.size()])
{
path.push_back(i);
dfs(s,t,i+1,path,res);
path.pop_back();
}
}
}
void dfs2(vector<vector<int>>& cnt, const string& t, vector<int>& path, vector<vector<int>>& res)
{
if (path.size() == t.length())
{
res.emplace_back(path);
return;
}
for (auto& item : cnt[t[path.size()]-'A'])
{
if (path.empty())
{
path.push_back(item);
dfs2(cnt,t,path,res);
path.pop_back();
}
else
{
if (item <= path.back())
continue;
path.push_back(item);
dfs2(cnt,t,path,res);
path.pop_back();
}
}
}
};