Programación dinámica: el problema de subsecuencia común más largo
Los pasos generales de la programación dinámica:
-
Análisis de la estructura del problema
Dadas dos secuencias X [n], Y [m], encuentre la longitud de la subsecuencia común más larga C [n] [m] de X [n], Y [m] -
Establecimiento de
una relación recursiva Utilice un ejemplo específico para analizar los caracteres al final de la secuencia:Caso 1: Los caracteres finales X [n], Y [m] son diferentes
Caso 2: Los caracteres finales X [n], Y [m] son iguales.
Veamos primero el Caso 1 : Los caracteres finales X [n], Y [m] son diferentes. 1 Hay dos posibilidades:
(1) Eliminar el último carácter de Y [m], a saber C [7] [6-1] +0:
(2) Eliminar el último carácter de X [m], a saber C [7-1] [6 ] +0:
Entonces la relación recursiva es: C [i, j] = max {C [i -1, j], C [i, j-1]}
Veamos el Caso 2 : X [n], Y [m] Los caracteres finales son los mismos, hay tres posibilidades en el caso 2:
(1) Los caracteres finales X [n], Y [m] se seleccionan al mismo tiempo y se ocultan, el siguiente paso es C [7-1,6-1] + 1
pero dos Esos no aparecen necesariamente en la subsecuencia más larga, por lo que hay dos posibilidades (2) y (3):
(2) Elimina el último carácter de Y [m], es decir, C [7] [6-1] +0:
(3) Quite los caracteres al final de X [m], es decir, C [7-1] [6] +0:
Estas tres posibilidades no necesitan ser resueltas, el análisis muestra que C [i-1, j-1] +1> = max {C [i, j -1], C [i-1, j], por lo que la relación recursiva final es: C [i, j] = C [i -1, j-1] +1 -
Cálculo ascendente
(1) Inicialización: C [i, 0] = C [0, j] = 0; cuando la longitud de una secuencia es 0, la longitud de la subsecuencia común más larga es 0
(2) Fórmula recursiva:
-
Seguimiento de la solución óptima
Construya una matriz de seguimiento rec [n] para registrar el origen de los subproblemas
Diagrama de algoritmo
Código
#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;
}