115. 不同的子序列
题目:115. 不同的子序列 - 力扣(LeetCode)
题解:代码随想录 (programmercarl.com)
没感觉有多难呀。。。
solution
public class Solution {
public int NumDistinct(string s, string t) {
int n = s.Length;
int m = t.Length;
int[,] dp = new int[n,m];
dp[0,0] = s[0] == t[0] ? 1 : 0;
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < m; j ++)
{
if(i != 0 && j == 0) dp[i,0] = s[i] == t[0] ? dp[i-1,0] + 1 : dp[i-1,0];
if(i != 0 && j != 0)
{
if(s[i] == t[j]) dp[i,j] = dp[i-1,j-1] + dp[i-1,j];
else dp[i,j] = dp[i-1,j];
}
}
}
return dp[n-1,m-1];
}
}
summary
dp:
1、dp[i,j]:包含0-i下标元素的t子串中出现包含0-j下标的s子串个数
2、递推:
t[ i ] == s[ j ]:包含两种情况:取t[ i ]:dp[i-1,j-1] / 不取t[ i ]:dp[i-1,j]
t[ i ] != s[ j ]:dp[i-1,j]
3、初始化:
因为dp的值由上一行和同行左边共同得到,需要初始化第一行第一列
第一列除第一个外应该初始化为0,与默认情况相同,不需要再显式初始化
583. 两个字符串的删除操作
题目:583. 两个字符串的删除操作 - 力扣(LeetCode)
题解:代码随想录 (programmercarl.com)
solution
public class Solution {
public int MinDistance(string word1, string word2) {
int m = word1.Length;
int n = word2.Length;
int[,] dp = new int[m, n];
dp[0,0] = word1[0] == word2[0] ? 0 : 2;
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j ++)
{
if(i == 0 && j != 0) dp[0,j] = word1[0] == word2[j] ? j : dp[0,j-1] + 1;
if(i != 0 && j == 0) dp[i,0] = word1[i] == word2[0] ? i : dp[i-1,0] + 1;
if(i != 0 && j != 0)
{
if(word1[i] != word2[j]) dp[i,j] = Math.Min(dp[i-1,j], dp[i,j-1]) + 1;
else dp[i,j] = dp[i-1,j-1];
}
}
}
return dp[m-1,n-1];
}
}
summary
dp:
1、dp[i,j]:包含0-i下标元素的t子串中出现包含0-j下标的s子串个数
2、递推:
t[ i ] == s[ j ]:包含两种情况:取t[ i ]:dp[i-1,j-1] / 不取t[ i ]:dp[i-1,j]
t[ i ] != s[ j ]:dp[i-1,j]
3、初始化:
因为dp的值由上一行和同行左边共同得到,需要初始化第一行第一列
第一列除第一个外应该初始化为0,与默认情况相同,不需要再显式初始化
72. 编辑距离
题目:72. 编辑距离 - 力扣(LeetCode)
题解:代码随想录 (programmercarl.com)
切入点是增 / 删 / 改三种递推方式
solution
public class Solution {
public int MinDistance(string word1, string word2) {
int m = word1.Length;
int n = word2.Length;
if(m == 0 || n == 0) return n == 0 ? m : n;
int[,] dp = new int[m, n];
for(int i = 0; i < m; i ++)
{
for(int j = 0; j < n; j ++)
{
if(i == 0 && j == 0) dp[0,0] = word1[i] == word2[j] ? 0 : 1;
else if(i == 0 && j != 0) dp[0,j] = word1[0] == word2[j] ? j : dp[0, j-1] + 1;
else if(i != 0 && j == 0) dp[i,0] = word1[i] == word2[0] ? i : dp[i-1,0] + 1;
else
{
if(word1[i] == word2[j]) dp[i,j] = dp[i-1, j-1];
else dp[i,j] = Math.Min(dp[i, j-1], Math.Min(dp[i-1,j], dp[i-1,j-1])) + 1; // 删/替换/增加
}
}
}
return dp[m-1,n-1];
}
}
summary
dp:
1、dp[i,j]:word1 0-i 子串转换尾word2 0-j 子串所需的最小步数
2、递推:
word1[ i ] == word2[ j ]:dp[i , j] = dp[i-1 , j-1]
word1[ i ] == word2[ j ]:
删除操作:dp[ i-1 , j ] + 1 删除word1[i],用0 - i-1子串转换 word2 0-j 子串
替换操作:dp[ i-1, j-1 ] + 1 替换word1[i]为word2[j],用0 - i-1子串转换 word2 0-j-1 子串
增加操作:dp[ i, j -1] + 1 用0 - i子串转换 word2 0-j-1 子串,末尾增加word2[j]
3、初始化:第一行和第一列