最长公共子序列和最长公共子串——C++

一、给定两个字符串S1和S2,求两个字符串的最长公共子序列的长度。 输入样例 ABCD AEBD 输出样例 3 解释 S1和S2的最长公共子序列为ABD,长度为3

思路 动态规划 LCS(m,n)表示S1[0…m)和S2[0…n)的最长公共子序列的长度 S1[m-1] == S2[n-1]: LCS(m, n) = 1 + LCS(m - 1, n - 1); S1[m-1] != S2[n-1]: LCS(m, n) = max(LCS(m - 1, n), LCS(m, n - 1))。

#include<iostream>
#include<vector>
#include<string>
using namespace std;

class Solution{
          
   
public:
	int max(int x, int y)
	{
          
   
		if (x <= y)
			return x;
		else
		{
          
   
			return y;
		}
	}
	//找出最长公共子序列的长度
	int lengthOflongestCommonSequence(string& str1, string& str2){
          
   
		int m = str1.length(), n = str2.length();
		if (m == 0 || n == 0)
			return 0;
		dp = vector<vector<int> >(m + 1, vector<int>(n + 1, 0));
		for (int i = 1; i < m + 1; ++i){
          
   
			for (int j = 1; j < n + 1; ++j){
          
   
				if (str1[i - 1] == str2[j - 1])
					dp[i][j] = dp[i - 1][j - 1] + 1;
				else
					dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
			}
		}
		return dp[m][n];
	}
	// 找出所有的最长公共子序列
	// 这里形参lcs_str不可以为引用,这里需要每次调用lcs_str都重新生成一个对象
	void PrintAllLCS(string& str1, string& str2, int i, int j, string lcs_str){
          
   
		//i, j为str1和str2的长度
		while (i > 0 && j > 0){
          
   
			if (str1[i - 1] == str2[j - 1]){
          
   
				lcs_str = str1[i - 1] + lcs_str;
				--i;
				--j;
			}
			else{
          
   
				if (dp[i - 1][j] > dp[i][j - 1])  //str1向前走
					--i;
				else if (dp[i - 1][j] < dp[i][j - 1])  //str2向前走
					--j;
				//str1和2向前均为LCS的元素
				else{
          
   
					PrintAllLCS(str1, str2, i - 1, j, lcs_str);
					PrintAllLCS(str1, str2, i, j - 1, lcs_str);
					return;
				}
			}
		}
		all_lcs.insert(lcs_str);
	}
	vector<vector<int>> dp;
	set<string> all_lcs;
};

int main()
{
          
   
    string s1 = "abcfbc";
    string s2 = "abfcab";
    Solution fir;
    string lcs_str;
    int res = fir.lengthOflongestCommonSequence(s1, s2);
    cout << res << endl;
    fir.PrintAllLCS(s1, s2, s1.length(), s2.length(), lcs_str);
    set<string>::iterator iter = fir.all_lcs.begin();
	while (iter != fir.all_lcs.end()) {
          
   
		cout << *iter++ << endl;
	}
    return 0;
}
/*
4
abcb
abfb
abfc
*/

二、求两个字符串的最长公共子串,要求子串连续 输入例子: bab caba 输出例子: 2 思路 动态规划 dp(m,n)表示S1[0…m)和S2[0…n)的最长公共子串的长度 当S1[m-1]==S2[n-1]: dp(m,n)=1+dp(m−1,n−1); 当S1[m-1]!=S2[n-1]: dp(m,n) = 0。

#include<iostream>
#include<vector>
#include<string>
using namespace std;

class Solution {
          
   
public:
	//输出最长公共子串的长度
	int lengthOflongestCommonSubstring(string& str1, string& str2){
          
   
		int m = str1.size(), n = str2.size();
		int res = 0;
		vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));
		for (int i = 1; i <= m; ++i){
          
   
			for (int j = 1; j <= n; ++j){
          
   
				if (str1[i - 1] == str2[j - 1])
					dp[i][j] = dp[i - 1][j - 1] + 1;
				else
					dp[i][j] = 0;
				if (res < dp[i][j])
					res = dp[i][j];
			}
		}
		return res;
	}
	//输出最长公共子串
	string LCS(string str1, string str2) {
          
   
		int m = str1.size();
		int n = str2.size();
		string res = "-1";
		int len = 0;
		int pos = 0;
		vector<vector<int>>dp(m + 1, vector<int>(n + 1, 0));
		for (int i = 1; i <= m; i++)
		{
          
   
			for (int j = 1; j <= n; j++)
			{
          
   
				if (str1[i - 1] == str2[j - 1])
				{
          
   
					dp[i][j] = dp[i - 1][j - 1] + 1;
				}
				else
				{
          
   
					dp[i][j] = 0;
				}
				if (len < dp[i][j])
				{
          
   
					len = dp[i][j];
					pos = i;
				}
			}
		}
		if (len == 0)
		{
          
   
			return res;
		}
		res = str1.substr(pos - len, len);
		return res;
	}
};

int main()
{
          
   

}
经验分享 程序员 微信小程序 职场和发展