最长公共子序列
思路:详见程序员代码面试指南
#include<iostream> #include<vector> #include<string> #include<algorithm> using namespace std; void cal_commonlen(string str1, string str2, vector<vector<int>>&dp){ dp[0][0] = str1[0] == str2[0] ? 1 : 0; for (int i = 1; i < dp.size(); i++){ dp[i][0] = max(str1[i] == str2[0] ? 1 : 0, dp[i - 1][0]); } for (int j = 1; j < dp[0].size(); j++){ dp[0][j] = max(str2[j] == str1[0] ? 1 : 0, dp[0][j - 1]); } for (int i = 1; i < dp.size(); i++){ for (int j = 1; j < dp[0].size(); j++){ dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); if (str1[i] == str2[j]){ dp[i][j] = max(dp[i - 1][j - 1] + 1, dp[i][j]); } } } //return dp[n - 1][m - 1]; } string getLongSequence(string s1, string s2){ int n = s1.size(); int m = s2.size(); vector<vector<int>>dp(n, vector<int>(m, 0)); cal_commonlen(s1, s2, dp); string res; int i = n-1; int j = m-1; while (i>=0||j>=0){ if (j > 0 && dp[i][j - 1] == dp[i][j]){ j--; } else if (i > 0 && dp[i - 1][j] == dp[i][j]){ i--; }//这里只能用else if因为向左或者向上每次只需移动一步就行 else{ if (i == 0 && j == 0){ if (s1[0] == s2[0]) { res.push_back(s1[i]); break; } else{ break; } } else{ res.push_back(s1[i]); i--; j--; } } } reverse(res.begin(), res.end()); return res; } int main(){ string s1 = "ABB1BC24fvqa", s2 = "AAAB34Cfhhvq"; string res = getLongSequence(s1, s2); cout << res << endl; system("pause"); return 0; }
最长公共字串
dp[i][j]代表必须把str1[i]和str2[j]当作公共字串最后一个字符的情况下的公共字串长度。
#include<iostream> #include<vector> #include<algorithm> #include<string> using namespace std; vector<vector<int>>getdp(string s1, string s2){ int n = s1.size(); int m = s2.size(); vector<vector<int>>dp(n, vector<int>(m, 0)); for (int i = 0; i < n; i++){ if (s1[i] == s2[0])dp[i][0] = 1; } for (int j = 0; j < m; j++){ if (s2[j] == s1[0])dp[0][j] = 1; } for (int i = 1; i < n; i++){ for (int j = 1; j < m; j++){ if (s1[i] == s2[j])dp[i][j] = dp[i - 1][j - 1] + 1; } } return dp; } string long_com_seq(string str1, string str2){ if (str1.size() == 0 || str2.size() == 0)return ""; string res; vector<vector<int>>dp; dp = getdp(str1, str2); int max = 0; int end = 0; for (int i = 0; i < dp.size(); i++){ for (int j = 0; j<dp[0].size(); j++){ if (dp[i][j]>max){ max = dp[i][j]; end = i; } } } return str1.substr(end - max + 1, max); } int main(){ vector<vector<int>>dp; string s1 = "bebcde"; string s2 = "bebcd"; string res=long_com_seq(s1, s2); for (int i = 0; i < dp.size(); i++){ for (int j = 0; j < dp[i].size(); j++){ cout << dp[i][j] << " "; } cout << endl; } cout << res << endl; system("pause"); return 0; }
最长递增子序列
#include<iostream> #include<vector> #include<algorithm> #include<string> using namespace std; vector<int> lengthOfLIS(vector<int>& nums) { if (nums.size() == 0)return vector<int>(); int n = nums.size(); vector<int>dp(n, 1);//dp[i]表示以arr[i]结尾的情况下,arr[0,1,2...i]中最长的子序列长度 for (int i = 0; i<n; i++){ for (int j = 0; j<i; j++){ if (nums[j]<nums[i]){//i前面的数j小于i所对应的数时,说明可以以j所对应的数作为倒数第二个数, //然后在很多倒数第二个数中选择以其结尾的最大递增子序列最大的那个作为倒数第二个数。 dp[i] = max(dp[i], dp[j] + 1); } } } return dp; } vector<int>getlist(vector<int>&a, vector<int>&dp){ int index = 0; int value = 0; for (int i = 0; i < dp.size(); i++){ if (dp[i]>value){ value = dp[i]; index = i; } } int j = index; vector<int>res; res.push_back(a[j]); for (int k = index - 1; k >= 0; k--){ if (dp[j] - dp[k] == 1 && a[k] < a[j]) { res.push_back(a[k]); j = k; } } return res; } int main(){ vector<int>a = { 1, 3, 6, 7, 9, 4, 10, 5, 6 }; vector<int>dp; vector<int>res; dp=lengthOfLIS(a); res = getlist(a, dp); reverse(res.begin(), res.end()); for (int i = 0; i < res.size(); i++){ cout << res[i] << " "; } system("pause"); return 0; }