动态规划之LCS

目录

最长公共子序列(Longest Common Subsequence)不要求连续

最长公共子串(Longest Common Substring)要求连续

三个字符串的最长公共子序列


最长公共子序列(Longest Common Subsequence)不要求连续

 https://leetcode-cn.com/problems/delete-operation-for-two-strings/

class Solution {
public:
    int minDistance(string word1, string word2) {
        int lena=word1.length();
        int lenb=word2.length();
        int a[lena+1][lenb+1] = {0};
        int len = 0;          
        for(int i=0;i<=lena;i++)
            for(int j=0;j<=lenb;j++){
                if(i==0||j==0)
                    a[i][j]=0;
                else if(word1[i-1]==word2[j-1]){
                    a[i][j]=a[i-1][j-1]+1;
                }
                else a[i][j]=max(a[i-1][j],a[i][j-1]);
            }
        return a[lena][lenb];        
    }
};

最长公共子串(Longest Common Substring)要求连续

https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/ 

class Solution {
public:
    int findLength(vector<int>& A, vector<int>& B) {
        int lena=A.size();
        int lenb=B.size();
        int a[lena+1][lenb+1] = {0};
        int len = 0;          
        for(int i=0;i<=lena;i++)
            for(int j=0;j<=lenb;j++){
                if(i==0||j==0)
                    a[i][j]=0;
                else if(A[i-1]==A[j-1]){
                    a[i][j]=a[i-1][j-1]+1;
                    len=max(len,a[i][j]);
                }
                else a[i][j]=0;
            }
        return len;        
    }
};

三个字符串的最长公共子序列

误区:先求出前两个字符串的最长公共子序列,然后再求他和第三个字符串的最长公共子序列。

举个简单的例子,三个字符串分别为abc、cab、c,前两个的最长公共子序列为ab,ab和c的公共子序列为空,实际上他们都有一个字符c,所以这种做法是错误的。

#include <iostream>
#include <string>
#include <algorithm>
 
using namespace std;
const int MAXN = 101;	//字符串的最大长度位MAXN-1
int a[MAXN][MAXN][MAXN];//a[i][j][k]表示第一个字符串的前i个字符,第二个字符串的前j个字符和
						//第三个字符串的前k个字符的最长公共子序列的长度
//函数返回三个字符串的最长公共子序列的长度
int commonLen(string strA, string strB, string strC)
{
	//n1、n2、n3分别为三个字符串的长度
	int n1 = strA.size();
	int n2 = strB.size();
	int n3 = strC.size();
 
	//字符串的个数可以是0-n,共n+1个可能,所以循环中是i<=n
	for(int i = 0; i <= n1; i++)
	for(int j = 0; j <= n2; j++)
	for(int k = 0; k <= n3; k++)
		if(i == 0 || j == 0 || k == 0)	//只要有一个序列的长度为0,公共子序列的长度为0
			a[i][j][k] = 0;
	//自底向上求a[i][j][k]
	for(int i = 1; i <= n1; i++)
		for(int j = 1; j <= n2; j++)
			for(int k = 1; k <= n3; k++)
			{
				if(strA[i - 1] == strB[j - 1] && strB[j - 1] == strC[k - 1])
					a[i][j][k] = a[i - 1][j - 1][k - 1] + 1;
				else 
					a[i][j][k] = max(max(a[i - 1][j][k], a[i][j - 1][k]),
									a[i][j][k -1]);
			}
	return a[n1][n2][n3];
}
 
int main()
{
	string str1, str2, str3;
	while(cin >> str1 >> str2 >> str3)
		cout << commonLen(str1, str2, str3) << endl;
 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a1058420631/article/details/88962669