最長公共子串行

2021-06-18 19:02:05 字數 1748 閱讀 9135

最長公共子串行(lcs)

題目描述:給你兩個陣列,可以是數字的,也可以是字串,我們假設是數字的!舉個例子:

x  =  1, 5, 6, 4, 1, 3, 7

y  =  1, 1, 6, 8, 3, 4, 7

求乙個新的陣列s,該陣列中的每個數均是x和y陣列中的公共數,並滿足原陣列中數字的前後關係,這樣的陣列有很多個,比如說          (1,1),(1,1,3,7),(1,6,7)等。同時s陣列要是長度最長的那個,像上面的(1,1,3,7),長度是4,那麼即為所求解!

做dp題目最重要的一點是能正確的構造出dp函式,如果能很好的構造出來,就成功一半了。

dp[i][j] 表示x陣列的前i位和y陣列的前j位之前的lcs,那麼它可以由前面三個狀態推出來。

0                                 if(i=0 || j=0) --初始化,不難理解,不管是x還是y陣列,只要有乙個長度是0,那麼s陣列就是0

dp[i][j] = max(dp[i-1][j],dp[i][j-1]    if(i,j>0 && x[i] != y[j]) --s陣列沒有新增數字,那麼只能從前面繼承來,乙個從x,乙個從y,看那個大

dp[i-1][j-1] + 1              if(i,j>0 && x[i] == y[j]) --如果是兩個相同,當然是把s陣列加1,可以看成x和y都繼承了

**很簡單,兩個for迴圈就可以了。

這樣我們可以總結出該問題的遞迴形式表達:

按照動態規劃的思想,對問題的求解,其實就是對子問題自底向上的計算過程。這裡,計算c[i][j]時,c[i-1][j-1]、c[i-1][j]、c[i][j-1]已經計算出來了,這樣,我們可以根據x[i]與y[j]的取值,按照上面的遞推,求出c[i][j],同時把路徑記錄在b[i][j]中(路徑只有3中方向:左上、左、上,如下圖)。

計算c矩陣的時間複雜度是o(m*n);根據b矩陣尋找最長公共子串行的過程,由於每次呼叫至少向上或向左移動一步,這樣最多需要(m+n)次就會i = 0或j = 0,也就是演算法時間複雜度為o(m+n)。

#include #include #include #include using namespace std;

void lcs_print(int **lcs_direction, char *str, int row, int column)

else if(lcs_direction[row][column] == 2)

else if(lcs_direction[row][column] == 3)

}int lcs(char *str1, char *str2)

for(int i = 0; i < nlen1; i++)

lcs_length[i][0] = 0;

for(int i = 0; i < nlen2; i++)

lcs_length[0][i] = 0;

for(int i = 0; i < nlen1; i++)

}cout<

else}}

lcs_print(lcs_direction, str1, nlen1 - 1, nlen2 - 1);

cout<

最長公共子串行 最長公共子串

1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...

最長公共子串行 最長公共子串

1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...

最長公共子串 最長公共子串行

子串要求連續 子串行不要求連續 之前的做法是dp求子序列 include include include using namespace std const int inf 0x3f3f3f3f const int mod 1000000007 string s1,s2 int dp 1010 10...