動的プログラミング:最も長い一般的なサブシーケンスの問題(C ++)

動的プログラミング:最も長く一般的なサブシーケンスの問題

動的プログラミングの一般的な手順:

  1. 問題構造分析
    2つのシーケンス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 2つの可能性があります:
    (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には3つの可能性があります。(1)X [n]、Y [m]の終了文字が同時に選択されて非表示になり、次のステップはC [7-1,6-1] +1ですが2つです。これらは必ずしも最長のサブシーケンスに表示されるとは限らないため、(2)と(3)の2つの可能性があります。(2)Y [m]の最後の文字、つまりC [7] [6-1] +0を削除します。(3)X [m]の最後の文字、つまりC [7-1] [6] +0を削除しますこれらの3つの可能性を解決する必要はありません。分析では、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