动态规划:最长公共子序列问题 (C++)

动态规划:最长公共子序列问题

动态规划的一般步骤:

  1. 问题结构分析
    给出两个序列X[n],Y[m],求X[n],Y[m]的最长公共子序列的长度C[n][m]

  2. 递推关系建立
    用一个具体的例子来分析序列末尾字符:

    情况1:X[n],Y[m]末尾字符不同在这里插入图片描述
    情况2:X[n],Y[m]末尾字符相同
    在这里插入图片描述
    先来看情况1:X[n],Y[m]末尾字符不同,情况1有两种可能:
    (1)去掉Y[m]末尾字符,即C[7][6-1]+0:
    在这里插入图片描述
    (2)去掉X[m]末尾字符,即C[7-1][6]+0:
    在这里插入图片描述
    所以递归关系为:C[i,j]= max { C[i -1,j], C[i,j-1] }
    在这里插入图片描述
    再来看情况2:X[n],Y[m]末尾字符相同,情况2有三种可能:
    (1)X[n],Y[m]末尾字符同时选取,并隐去后,下一步的得C[7-1,6-1] + 1在这里插入图片描述
    但两者并不一定都出现在最长子序列中,所以就有了(2)(3)两种可能:
    (2)去掉Y[m]末尾字符,即C[7][6-1]+0:
    在这里插入图片描述
    (3)去掉X[m]末尾字符,即C[7-1][6]+0:
    在这里插入图片描述
    但这三种可能并不是需要都求解,分析得C[i-1,j-1]+1 >= max{C[i,j -1],C[i-1,j],所以最终的递归关系为:C[i,j]= C[i -1,j-1]+1

  3. 自底向上计算
    (1)初始化:C[i,0]= C[0,j]= 0;某序列长度为0时,最长公共子序列长度为0
    (2)递推公式:
    在这里插入图片描述

  4. 最优方案追踪
    构造追踪数组rec[n],记录子问题来源
    在这里插入图片描述在这里插入图片描述

算法图解

在这里插入图片描述

代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

string X,Y;
int C[1001][1001];//记录公共子序列长度

int main(){
    
    
	cin >> X >> Y;
	int n = X.length(), m = Y.length();
	
	//初始化 
	for(int i=0; i<n; i++)
		C[i][0] = 0;
	for(int j=0; j<n; j++)
		C[0][j] = 0;
	
	for(int i=1; i<=n; i++){
    
    
		for(int j=1; j<=m; j++){
    
    
			if(X[i]==Y[j])
				C[i][j] = C[i-1][j-1]+1;
			else 
				C[i][j] = max(C[i][j-1],C[i-1][j]);
		}
	}
	
	cout << C[n][m] << endl;//输出最长公共子序列长度
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44524918/article/details/109002874