Problem:
The longest common subsequence is the search for a subsequence of two given sequences, which appear in the same order in the two sequences, but are not necessarily contiguous.
For example, sequence X=abcbdab,y=bdcaba. The sequence BCA is a common sub-sequence of x and Y, but is not the longest common subsequence of x and Y, the subsequence BCBA is an LCS of X and Y, and the sequence Bdab is also.
Ideas:
1, the simplest method is the violent enumeration.
First enumerate all the sub-sequences of x, then check if Y is a subsequence, and record the longest subsequence. When the complexity of the method is too high, assuming that X is the length of M, then the number of sub-sequences of X is 2^m, and the complexity of the magnitude is impractical.
2, dynamic planning ideas.
Set x=<x1,x2,..., xm> and Y=<y1,y2,..., yn> are two sequences, and LCS (Xm,yn) represents a string ending with XM and a longest common subsequence of a string ending in yn, as you can see
If Xm=yn, then LCS (xm,yn) = Xm + LCS (xm-1,yn-1).
If Xm!=yn, then LCS (xm,yn) = max{LCS (Xm-1, yn), LCS (Xm, Yn-1)}
Longest common sub-sequence length:
State transition equation:
Initial state: dp[i][j]=0 If i==0 | | J==0
Transfer equation: dp[i][j] = dp[i-1][j-1] + 1 if (x[i-1]==y[j-1])
DP[I][J] = max (Dp[i-1][j], dp[i][j-1]) if (x[i-1]!=y[j-1])
The longest common subsequence:
Through the state transition equation, the oldest sequence can be reversed, if x[i-1]==y[j-1] && dp[i][j]==dp[i-1][j-1]+1, then x[i-1] is the element of the oldest sequence, otherwise if X[I-1]==Y[J-1] && Dp[i-1][j]>dp[i][j-1], then i--, otherwise j--, this will get a reverse of the eldest son sequence, see the reference code.
Analysis of Complexity:
The time complexity of the above thought is O (m*n), and the space complexity is O (m*n);
DP[I][J] = dp[i-1][j-1] + 1 if (x[i-1]==y[j-1])
DP[I][J] = max (Dp[i-1][j], dp[i][j-1]) if (x[i-1]!=y[j-1])
It can be seen from the state transition equation that, if only the longest common subsequence length is involved, each transfer is only related to the previous state, so the spatial complexity can be reduced from m*n to 2*n, saving only current and previous states, and the time complexity is constant.
Code:
#include <iostream>#include<vector>using namespacestd;intLCS (Char*STR1,intLen1,Char*STR2,intlen2) { //calculate length of LCSvector<vector<int> > DP (len1+1,vector<int> (len2+1,0)); for(intI=0; i<=len1;i++){ for(intj=0; j<=len2;j++){ if(i==0|| j==0) Dp[i][j]=0; Else{ if(str1[i-1]==str2[j-1]) Dp[i][j]=dp[i-1][j-1]+1; ElseDp[i][j]=max (dp[i-1][j],dp[i][j-1]); } } } //Record the LCS intlen=Dp[len1][len2]; CharLcsarr[len]; Lcsarr[len]=' /'; inti=len1,j=Len2; while(I &&j) { if(str1[i-1]==str2[j-1] && dp[i][j]==dp[i-1][j-1]+1) {lcsarr[--len]=str1[i-1]; I--; J--; } Else if(str1[i-1]!=str2[j-1] && dp[i-1][j]>dp[i][j-1]) I--; ElseJ--; } cout<<"Length of LCS is:"<<len<<Endl; cout<<"subsequency of LCS is:"<<lcsArr<<Endl; returndp[len1][len2];}intMain () {Charstr1[]="ABCD"; Charstr2[]="BD"; intlen1=sizeof(STR1)/sizeof(str1[0])-1; intLen2=sizeof(STR2)/sizeof(str2[0])-1; cout<< LCS (STR1,LEN1,STR2,LEN2) <<Endl; return 0;}
intLCS2 (Char*STR1,intLen1,Char*STR2,intlen2) { //Only to calculate length of LCS//Reduce the space complexity from m*n to 2*nvector<vector<int> > DP (2,vector<int> (len2+1,0)); intK; for(intI=0; i<=len1;i++) {k=i&1; for(intj=0; j<=len2;j++){ if(j==0) Dp[k][j]=0; Else{ if(str1[i-1]==str2[j-1]) Dp[k][j]=dp[1-k][j-1]+1; ElseDp[k][j]=max (dp[1-k][j],dp[k][j-1]); } }} cout<<"Length of LCS is:"<<dp[k][len2]<<Endl; returndp[k][len2];}Operation Result:
(string) The longest common sub-sequence (LONGEST-COMMON-SUBSEQUENCE,LCS)