日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(字符串)最长公共子序列(Longest-Common-Subsequence,LCS)

發布時間:2023/12/19 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (字符串)最长公共子序列(Longest-Common-Subsequence,LCS) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題:

最長公共子序列就是尋找兩個給定序列的子序列,該子序列在兩個序列中以相同的順序出現,但是不必要是連續的。

例如序列X=ABCBDAB,Y=BDCABA。序列BCA是X和Y的一個公共子序列,但是不是X和Y的最長公共子序列,子序列BCBA是X和Y的一個LCS,序列BDAB也是。

思路:

1、最簡單的方法就是暴力枚舉。

先列舉X所有的子序列,然后檢查是否為Y的子序列,并記錄最長的子序列。當該方法復雜度太高,假設X的長度為m,則X的子序列個數為2^m,指數級的復雜度是不實際的。

2、動態規劃思想。

設X=<x1,x2,…,xm>和Y=<y1,y2,…,yn>為兩個序列,LCS(Xm,Yn)表示以Xm結尾的字符串和以Yn結尾的字符串的一個最長公共子序列,可以看出

如果xm=yn,則LCS ( Xm,Yn?) = xm?+ LCS ( Xm-1,Yn-1?)。

如果xm!=yn,則LCS( Xm,Yn )= max{ LCS ( Xm-1, Yn ), LCS ( Xm, Yn-1?) }

最長公共子序列長度:

狀態轉移方程:

初始狀態:dp[i][j]=0 if i==0 || j==0

轉移方程: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])

最長公共子序列:

通過狀態轉移方程,可以逆推出最長子序列,如果x[i-1]==y[j-1] && dp[i][j]==dp[i-1][j-1]+1,則x[i-1]為最長子序列的元素,否則如果x[i-1]==y[j-1] && dp[i-1][j]>dp[i][j-1],則i--,否則j--,這樣就得到一個倒序的最長子序列,具體見參考代碼。

復雜度分析:

上述思路的時間復雜度為O(m*n),空間復雜度也為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])

從狀態轉移方程可以看到,如果只求最長公共子序列長度的話,每一次轉移的時候只與前一狀態有關,因此空間復雜度可以從m*n降為2*n,只保存當前和前一狀態,時間復雜度不變。

代碼:

#include <iostream> #include <vector>using namespace std;int LCS(char *str1,int len1,char *str2,int len2){// calculate length of LCSvector<vector<int> > dp(len1+1,vector<int>(len2+1,0));for(int i=0;i<=len1;i++){for(int j=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 LCSint len=dp[len1][len2];char lcsArr[len];lcsArr[len]='\0';int i=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;return dp[len1][len2]; }int main() {char str1[]="abcd";char str2[]="bd";int len1=sizeof(str1)/sizeof(str1[0])-1;int len2=sizeof(str2)/sizeof(str2[0])-1;cout << LCS(str1,len1,str2,len2) << endl;return 0; } int LCS2(char *str1,int len1,char *str2,int len2){// 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));int k;for(int i=0;i<=len1;i++){k=i&1;for(int j=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;return dp[k][len2]; }

運行結果:

?

轉載于:https://www.cnblogs.com/AndyJee/p/4469196.html

總結

以上是生活随笔為你收集整理的(字符串)最长公共子序列(Longest-Common-Subsequence,LCS)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。