[Algo] 二维动态规划2
1. 不同的子序列
// 4. 不同的子序列
// https://leetcode.cn/problems/distinct-subsequences/
long numDistinct(string s, string t) {int n = s.length(), m = t.length();vector<vector<long>> dp(n + 1, vector<long>(m + 1)); // dp[i][j] - s[0...i-1]中包含子序列t[0...j-1]的个数// 状态转移方程 - dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1](s[i - 1] == t[j - 1])for (int i = 0; i <= n; i++) dp[i][0] = 1;for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++)dp[i][j] = (dp[i - 1][j] + (s[i - 1] == t[j - 1] ? dp[i - 1][j - 1] : 0)) % MOD;return dp[n][m];
}
long numDistinct_(string s, string t) {int n = s.length(), m = t.length();vector<long> dp(m + 1);dp[0] = 1;for (int i = 1; i <= n; i++) for (int j = m; j >= 1; j--)if (s[i - 1] == t[j - 1]) dp[j] = (dp[j] + dp[j - 1]) % MOD;return dp[m];
}
2. 编辑距离
// 5. 编辑距离
// https://leetcode.cn/problems/edit-distance/
// 插入一个字符,代价a
// 删除一个字符,代价b
// 替换一个字符,代价c
int MinDistance(string word1, string word2, int a, int b, int c) {int n = word1.length(), m = word2.length();vector<vector<int>> dp(n + 1, vector<int>(m + 1));// 状态转移方程 - (1)word1[i - 1] == word2[j - 1], dp[i][j] = dp[i - 1][j - 1]// (2)word1[i - 1] != word2[j - 1], dp[i][j] = min(dp[i - 1][j - 1] + c, dp[i][j - 1] + a, dp[i - 1][j] + b)for (int j = 1; j <= m; j++) dp[0][j] = j * a;for (int i = 1; i <= n; i++) dp[i][0] = i * b;for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++)if (word1[i - 1] == word2[j - 1]) dp[i][j] = dp[i - 1][j - 1];else dp[i][j] = min(min(dp[i - 1][j - 1] + c, dp[i][j - 1] + a), dp[i - 1][j] + b);return dp[n][m];
}
3. 交错字符串
// 6. 交错字符串
// https://leetcode.cn/problems/interleaving-string/
bool isInterleave(string s1, string s2, string s3) {int n = s1.length(), m = s2.length(), k = s3.length();if (n + m != k) return false;vector<vector<bool>> dp(n + 1, vector<bool>(m + 1, false)); // dp[i][j] - s1[0...i-1]与s2[0...j-1]能否拼出s3[0...i+j-1]// 状态转移方程 - (1)s1[i - 1] == s3[i + j - 1], dp[i - 1][j]// (2)s2[j - 1] == s3[i + j - 1], dp[i][j - 1]dp[0][0] = true;for (int j = 1; j <= m; j++){if (s2[j - 1] != s3[j - 1]) break;dp[0][j] = true;}for (int i = 1; i <= n; i++){if (s1[i - 1] != s3[i - 1]) break;dp[i][0] = true;}for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++)dp[i][j] = (s1[i - 1] == s3[i + j - 1] && dp[i - 1][j]) || (s2[j - 1] == s3[i + j - 1] && dp[i][j - 1]);return dp[n][m];
}