Dynamic programming: the longest common subsequence problem
The general steps of dynamic programming:
-
Problem structure analysis
Given two sequences X[n], Y[m], find the length of the longest common subsequence C[n][m] of X[n], Y[m] -
Recursion relationship establishment
Use a specific example to analyze the characters at the end of the sequence:Case 1: X[n], Y[m] end characters are different
Case 2: X[n], Y[m] end characters are the same.
Let’s first look at Case 1 : X[n], Y[m] end characters are different. 1 There are two possibilities:
(1) Remove the last character of Y[m], namely C[7][6-1]+0:
(2) Remove the last character of X[m], namely C[7-1][6 ]+0:
So the recursive relationship is: C[i,j]= max {C[i -1,j], C[i,j-1]}
Let’s look at Case 2 : X[n],Y[m] The end characters are the same, there are three possibilities in case 2:
(1) X[n], Y[m] end characters are selected at the same time and hidden, the next step is C[7-1,6-1] + 1
but two Those do not necessarily appear in the longest subsequence, so there are two possibilities (2) and (3):
(2) Remove the last character of Y[m], that is, C[7][6-1]+0:
(3) Remove the characters at the end of X[m], that is, C[7-1][6]+0:
These three possibilities do not need to be solved, the analysis shows that C[i-1,j-1]+1> = max{C[i,j -1],C[i-1,j], so the final recursive relationship is: C[i,j]= C[i -1,j-1]+1 -
Bottom-up calculation
(1) Initialization: C[i,0]= C[0,j]=0; when the length of a sequence is 0, the length of the longest common subsequence is 0
(2) Recursive formula:
-
Optimal solution tracking
Construct tracking array rec[n] to record the source of sub-problems
Algorithm diagram
Code
#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;
}