动态规划算法——最长公共子序列求法
????? 給定序列X={ X1,X2,....Xn }、Y={ Y1,Y2,...Ym }找出它們的最大子序列Z={ Z1,Z2,...Zk }比如:X={ A,B ,C,B,D,A,B }、Y={ B,D,C,A,B,A },它們的最大子序列
Z={ B,C,B,A}。
????? c[i][j]表示長度為i的X和長度為j的Y的最長子序列,c[0][j]=0,c[i][0]=0,任一序列與空序列的最長子序列為0。{ X1,X2,.....Xi }、{ Y1,Y2,....Yj },最大子序列長度分2種情況:Xi==Yj,則其長度是{ X1,X2,.....Xi-1 }、{ Y1,Y2,....Yj -1}最長子序列加1,即c[i][j]=c[i-1][j-1]+1,若Xi !=Yj,其長度為{ X1,X2,.....Xi -1}、{ Y1,Y2,....Yj }和
{ X1,X2,.....Xi }、{ Y1,Y2,....Yj -1}中最大的次序列長度,即:c[i][j]=max{ c[i-1][j]? ,c[i][j-1] }。
????????????????????????????????????????????????????? ?
dynamic.h
#pragma once #include<iostream> #include<vector> #include<string> using namespace std; class Lseq { public:void insertX(string x);//插入序列Xvoid insertY(string y);//插入序列Yvoid find();//尋找最大子序列void show();//輸出最大子序列void maxseq(int xi,int yj); private:vector<string> X;//輸入序列Xvector<string> Y;//輸入序列Yvector<string>Z;//最長公共子序列vector<vector<int> > c;//公共子序列的長度vector<vector<int> >path;//記錄路徑 };dynamic.cpp
#include "stdafx.h" #include"dynamic.h" #include<iostream> #include<vector> #include<string> using namespace std;void Lseq::insertX(string x) {X.push_back(x); } void Lseq::insertY(string y) {Y.push_back(y); } void Lseq::find() {//分配c、path大小int nx=X.size();int ny=Y.size();c.resize(nx+1);path.resize(nx);for(int i=0;i<c.size();i++){c[i].resize(ny+1);if(i<nx)path[i].resize(ny);}for(int i=0;i<c.size();i++){c[i][0]=0; //Y長度為0,則公共的子序列長度為0}for(int i=0;i<ny+1;i++){c[0][i]=0;//X的長度為0,則公共的子序列長度為0}for(int i=0;i<nx;i++)for(int j=0;j<ny;j++){if(X[i]==Y[j]) {c[i+1][j+1]=c[i][j]+1;path[i][j]=0;//相等標記}else if(c[i+1][j]>c[i][j+1]){c[i+1][j+1]=c[i+1][j];path[i][j]=1; }else{c[i+1][j+1]=c[i][j+1];path[i][j]=2;}} } void Lseq::show() {find();int nx=X.size();int ny=Y.size();cout<<"最長子序列長度:"<<c[nx][ny]<<endl;cout<<"最長子序列為:";maxseq(nx-1,ny-1);//采用遞歸倒序的需找最長子序列cout<<endl; } void Lseq::maxseq(int xi,int yj) {if((xi<0)||(yj<0))return;if(path[xi][yj]==0){maxseq(xi-1,yj-1);cout<<X[xi]<<" ";}else if(path[xi][yj]==1)maxseq(xi,yj-1);elsemaxseq(xi-1,yj); }
Algorithm-dynamic2.cpp
補充:對函數void maxseq(int xi,int yj);的說明,其主要功能是用于尋找最大的子序列。采用逆序查找,例中path 矩陣為:
X={ A,B ,C,B,D,A,B }、Y={ B,D,C,A,B,A }。開始:
(1)xi=6,yj=5;判斷path[6][5]==0?即X[6]與Y[5]是否相等,不相等。path[6][5]=2即xi=5,yj=5 這表明c[xi][yj]=c[xi-1][yj]
(2)在X={ A,B ,C,B,D,A }、Y={ B,D,C,A,B,A }中查找最大序列,path[5][5]==0,所以X[5]與Y[5]相等,X[5]為最大子序列中的一個,X[5]=A壓入棧中。xi=xi-1=4,yj=yj-1=4
(3)X={ A,B ,C,B,D }、Y={ B,D,C,A,B }中查找最大序列,path[4][4]==2,xi=xi-1=3,yj=yj=4?
(4)X={ A,B ,C,B }、Y={ B,D,C,A,B }中查找最大序列,path[3][4]==0,X[3]為最大子序列中一個,X[3]=B壓入棧中,xi=xi-1=2,yj=yj-1=3
(5)X={ A,B ,C }、Y={ B,D,C,A }中查找最大序列,path[2][3]==1,xi=xi=2,yj=yj-1=2
(6)X={ A,B ,C }、Y={ B,D,C }中查找最大序列,path[2][2]==0,X[2]為最大子序列中一個,X[2]=C壓入棧中,xi=xi-1=1,yj=yj-1=1;
(7)X={ A,B? }、Y={ B,D }中查找最大序列,path[1][1]==1,xi=xi=1,yj=yj-1=0;
(8)X={ A,B? }、Y={ B }中查找最大序列,path[1][0]==0,X[1]為最大子序列中一個,X[1]=B壓入棧中,xi=xi-1=0,yj=yj-1=-1;
(9)yj<0返回,則最大子序列查找到,輸出:B C B A
總結
以上是生活随笔為你收集整理的动态规划算法——最长公共子序列求法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: foxmail不能添加google账户
- 下一篇: DOTS是什么?