用C++写一段代码并附上注解。应用动态规划法用文件输入方式输入两个长度任意的字符串打印出生成的二维矩阵和所有的最长公共子序列。并分析时间和空间复杂度。
注:本代码采用LCS(最长公共子序列)算法,时间复杂度为O(mn),空间复杂度为O(mn),其中m和n分别为两个字符串的长度。
代码如下:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string s1, s2;
ifstream fin("input.txt"); // 从文件中读取输入字符串
fin >> s1 >> s2;
fin.close();
int len1 = s1.size(), len2 = s2.size();
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1)); // 二维矩阵dp,用于存储LCS长度
for (int i = 1; i <= len1; i++)
{
for (int j = 1; j <= len2; j++)
{
if (s1[i - 1] == s2[j - 1]) // 当前字符相等
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else // 当前字符不相等
{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
cout << "生成的二维矩阵为:" << endl;
for (int i = 0; i <= len1; i++)
{
for (int j = 0; j <= len2; j++)
{
cout << dp[i][j] << " ";
}
cout << endl;
}
cout << "所有的最长公共子序列为:" << endl;
vector<char> res; // 存储最长公共子序列
int i = len1, j = len2;
while (i > 0 && j > 0)
{
if (s1[i - 1] == s2[j - 1])
{
res.push_back(s1[i - 1]);
i--;
j--;
}
else if (dp[i - 1][j] >= dp[i][j - 1])
{
i--;
}
else
{
j--;
}
}
reverse(res.begin(), res.end()); // 由于是从后往前加入res的,所以需要翻转一下
for (char c : res)
{
cout << c << " ";
}
return 0;
}
注解如下:
-
头文件包含了iostream、fstream、string、vector和algorithm。其中,iostream和fstream用于文件输入输出,string用于处理字符串,vector用于存储二维矩阵dp,algorithm用于reverse函数的调用。
-
main函数中,首先定义了两个字符串s1和s2,并通过ifstream从文件中读取输入字符串。然后,求出两个字符串的长度len1和len2,并定义了一个二维矩阵dp,用于存储LCS长度。
-
通过双重循环遍历两个字符串的所有字符,如果当前字符相等,则在dp[i][j]中加上dp[i-1][j-1]+1的长度。如果当前字符不相等,则取dp[i-1][j]和dp[i][j-1]的最大值。
-
输出生成的二维矩阵dp。
-
通过双指针i和j,从后往前遍历dp数组,将最长公共子序列存储在res数组中。当s1[i-1]等于s2[j-1]时,将当前字符加入res数组中,i和j都减1。当dp[i-1][j]大于等于dp[i][j-1]时,i减1。否则,j减1。
-
最后,将res数组中的字符输出即可。
-
时间复杂度为O(mn),其中m和n分别为两个字符串的长度。空间复杂度为O(mn),因为需要存储一个二维矩阵dp
原文地址: http://www.cveoy.top/t/topic/fV70 著作权归作者所有。请勿转载和采集!