任务描述 给定两个字符串S和T,保证S的长度不小于T的长度,问至少修改S的多少个字符,可以令T成为S的子序列。 输入格式 两行。第一行是字符串S,第二行是字符串T。保证S的长度不小于T的长度,S的长度范围在0~1000之间。 输出格式 一个非负整数,表示需要变换的次数。
时间: 2024-11-17 18:28:16 浏览: 31
这个问题描述的是一个经典的动态规划问题,通常被称为“最长公共子序列”(Longest Common Subsequence, LCS)问题。你可以使用动态规划的方法来解决,其中状态转移方程涉及到计算两个子串的LCS长度。
下面是解决这个问题的基本步骤:
1. 定义一个二维数组dp,其大小为(S.length() + 1) x (T.length() + 1),用于存储S的每个前缀和T的每个后缀的LCS长度。
2. 初始化数组的第一行和第一列,因为单独看,S的一个空前缀和T的一个字符都可以构成子序列,所以它们的LCS长度分别为0和1。
3. 遍历dp数组,对于每个位置(i, j),如果S[i-1] == T[j-1],则dp[i][j] = dp[i-1][j-1] + 1(意味着当前字符匹配,LCS长度加一),否则dp[i][j] = max(dp[i-1][j], dp[i][j-1])(意味着当前字符不匹配,取之前不包含S[i-1]或T[j-1]的最大LCS长度)。
4. dp[S.length()][T.length()]即为最终答案,表示使得T成为S子序列所需的最小修改次数,等于dp[S.length()][T.length()] - T.length()(因为T本身也是一个子序列,但可能不是最长的)。
这里是C++代码实现这个算法:
```cpp
#include <iostream>
#include <vector>
int lcsLength(std::string S, std::string T) {
int m = S.size(), n = T.size();
std::vector<std::vector<int>> dp(m+1, std::vector<int>(n+1, 0));
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (S[i-1] == T[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = std::max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[m][n] - n;
}
int main() {
std::string S, T;
std::cin >> S >> T;
int answer = lcsLength(S, T);
std::cout << "至少需要修改 " << answer << " 个字符,可以使 T 成为 S 的子序列." << std::endl;
return 0;
}
```
阅读全文