最长子序列之LCSlength算法详解.docx
《最长子序列之LCSlength算法详解.docx》由会员分享,可在线阅读,更多相关《最长子序列之LCSlength算法详解.docx(8页珍藏版)》请在冰豆网上搜索。
![最长子序列之LCSlength算法详解.docx](https://file1.bdocx.com/fileroot1/2023-7/12/8d04305f-f903-424f-a27d-380e0421b17e/8d04305f-f903-424f-a27d-380e0421b17e1.gif)
最长子序列之LCSlength算法详解
1003
1003CommonSubsequence
Asubsequenceofagivensequenceisthegivensequencewithsomeelements(possiblenone)leftout.GivenasequenceX=anothersequenceZ=isasubsequenceofXifthereexistsastrictlyincreasingsequenceofindicesofXsuchthatforallj=1,2,...,k,xij=zj.Forexample,Z=isasubsequenceofX=withindexsequence<1,2,4,6>.GiventwosequencesXandYtheproblemistofindthelengthofthemaximum-lengthcommonsubsequenceofXandY.
Theprograminputisfromatextfile.Eachdatasetinthefilecontainstwostringsrepresentingthegivensequences.Thesequencesareseparatedbyanynumberofwhitespaces.Theinputdataarecorrect.Foreachsetofdatatheprogramprintsonthestandardoutputthelengthofthemaximum-lengthcommonsubsequencefromthebeginningofaseparateline.
SampleInput
abcfbcabfcab
programmingcontest
abcdmnp
SampleOutput
4
2
0
C++语言:
Codee#8958
01#include
02#include
03usingnamespacestd;
04#defineN105
05intdp[N+1][N+1];
06charstr1[N],str2[N];
07intmaxx(inta,intb)
08{
09if(a>b)
10returna;
11returnb;
12}
13intLCSL(intlen1,intlen2)
14{
15inti,j;
16intlen=maxx(len1,len2);
17for(i=0;i<=len;i++)
18{
19dp[i][0]=0;dp[0][i]=0;
20}
21for(i=1;i<=len1;i++)
22for(j=1;j<=len2;j++)
23
24{
25if(str1[i-1]==str2[j-1])
26{
27dp[i][j]=dp[i-1][j-1]+1;
28}
29else
30{
31dp[i][j]=maxx(dp[i-1][j],dp[i][j-1]);
32}
33}
34returndp[len1][len2];
35}
36intmain()
37{
38while(cin>>str1>>str2)
39
40{
41intlen1=strlen(str1);
42intlen2=strlen(str2);
43cout<44}
45return0;
46}
一、最长公共子序列(LongestCommonSubsequence:
LCS)
设有两个序列A[1...m]和B[1...n],分别对A和B进行划分子序列
A[1]A[1..2]A[1..3]...A[1..m]
B[1]B[1..2]B[1..3]...B[1..n]
依次求出A中的每个子序列(从A[1]开始)与B中每个子序列的最长公共子序列,并记录在数组C[m][n]中,C[i][j]表示A[1..i]和B[1..j]的最长公共子序列的长度。
递推公式如下:
①C[i][j]=0i=0orj=0
②C[i][j]=C[i-1][j-1]+1i!
=0andj!
=0andA[i]=B[j]
③C[i][j]=max{C[i-1][j],C[i][j-1]}i!
=0andj!
=0andA[i]!
=B[j]
路径记录:
记录路径即记录C[i][j]是怎么得来的,从递推公式②③知,C[i][j]的来源有三个:
C[i-1][j-1],C[i-1][j],C[i][j-1]。
如果是从C[i-1][j-1]得来,那么A[i]=B[j],是最长公共子序列中的一个元素。
可以设置一个数组P[m][n]来记录当前的C[i][j]是怎么得来的,P[m][n]的取值只能有三种,分别记为123。
构造最长公共子序列:
用递归的方法,检查P[i][j],初始i=m,j=n
如果p[i][j]=1,则记录C[i][j],然后递归处理P[i-1][j-1]
如果P[i][j]=2,不记录,递归处理P[i-1][j]
如果P[i][j]=3,不记录,递推处理P[i][j-1]
直到i=0orj=0
时间复杂度:
O(mn)
C++语言:
Codee#8959
01#include
02#include
03usingnamespacestd;
04#defineN105
05intdp[N+1][N+1];
06charstr1[N],str2[N];
07intmark[N+1][N+1];
08intmaxx(inta,intb)
09{if(a>b)returna;returnb;}
10voidLCSL(intlen1,intlen2)
11{
12inti,j;
13intlen=maxx(len1,len2);
14for(i=0;i<=len;i++)
15{
16dp[i][0]=0;dp[0][i]=0;
17}
18for(i=1;i<=len1;i++)
19for(j=1;j<=len2;j++)
20{
21if(str1[i-1]==str2[j-1])
22{
23dp[i][j]=dp[i-1][j-1]+1;
24mark[i][j]=1;
25}
26else
27{
28inta=dp[i-1][j];
29intb=dp[i][j-1];
30dp[i][j]=maxx(a,b);
31if(a>=b)
32mark[i][j]=2;
33else
34mark[i][j]=3;
35}
36}
37}
38voidLCS(inti,intj)
39{
40if(i==0||j==0)
41return;
42if(mark[i][j]==1)
43{
44LCS(i-1,j-1);
45cout<46}
47elseif(mark[i][j]==2)
48{
49LCS(i-1,j);
50}
51else
52LCS(i,j-1);
53}
54intmain()
55{
56while(cin>>str1>>str2)
57{
58memset(mark,0,sizeof(mark));
59intlen1=strlen(str1);
60intlen2=strlen(str2);
61LCSL(len1,len2);
62cout<63if(dp[len1][len2]!
=0)
64{
65LCS(len1,len2);
66cout<67}
68}
69system("pause");
70return0;