子串應該比較好理解,至於什麼是子串行,這裡給出乙個例子:有兩個母串
比如序列bo, bg, lg在母串cnblogs與belong中都出現過並且出現順序與母串保持一致,我們將其稱為公共子串行。最長公共子串行(longest common subsequence, lcs),顧名思義,是指在所有的子串行中最長的那乙個。子串是要求更嚴格的一種子串行,要求在母串中連續地出現。在上述例子的中,最長公共子串行為blog(cnblogs,belong),最長公共子串為lo(cnblogs, belong)。
對於母串
x=,x2,
⋯,xm
>
, y=,y2,
⋯,yn
>
,求lcs與最長公共子串。
假設 m
<
n
, 對於母串x
,我們可以暴力找出2m
個子序列,然後依次在母串y
中匹配,演算法的時間複雜度會達到指數級o(
n∗2m
) 。顯然,暴力求解不太適用於此類問題。假設z
=,z2,
⋯,zk
>
是x
與y
的lcs, 我們觀察到 ,則
zk=x
m=yn
,有zk
−1 是
xm−1
與yn−1
因此,求解lcs的問題則變成遞迴求解的兩個子問題。但是,上述的遞迴求解的辦法中,重複的子問題多,效率低下。改進的辦法——用空間換時間,用陣列儲存中間狀態,方便後面的計算。這就是動態規劃(dp)的核心思想了。
用二維陣列c[i][j]記錄串x1x
2⋯xi
與y1y2⋯y
j
的lcs長度,則可得到狀態轉移方程c[
i,j]
=⎧⎩⎨
⎪⎪0c
[i−1
,j−1
]+1max(c
[i,j
−1],
c[i−
1,j]
)i=0
orj=
0i,j
>0a
ndxi
=yji
,j>0a
ndxi
≠yj
**實現
public
static
intlcs
(string str1, string str2)
else
if (str1.charat(i-1) == str2.charat(j-1)) else }}
return c[len1][len2];
}
前面提到了子串是一種特殊的子串行,因此同樣可以用dp來解決。定義陣列的儲存含義對於後面推導轉移方程顯得尤為重要,糟糕的陣列定義會導致異常繁雜的轉移方程。考慮到子串的連續性,將二維陣列c[i
,j]
用來記錄具有這樣特點的子串——結尾為母串x1x
2⋯xi
與y1y2⋯y
j
的結尾——的長度。
得到轉移方程:
c[i,j]=
⎧⎩⎨⎪
⎪0c[
i−1,
j−1]
+10i
=0or
j=0x
i=yj
xi≠y
j
最長公共子串的長度為 max
(c[i
,j])
,i∈,
j∈。**實現
public
static
intlcs
(string str1, string str2)
else
if (str1.charat(i-1
) == str2.charat(j-1
)) else}}
return
result;
}
最長公共子串與最長公共子串行問題(動態規劃)
公共子串是連續的,而公共子串行不是連續的。x1 abcc x2 acbcc x1和x2的公共子串為 bcc 公共子串行為 abcc 我們來看一下兩個問題的轉移方程 最長公共子串 dp i j 0 if i 0 or j 0 dp i j dp i 1 j 1 1 if x1 i x2 j dp i ...
動態規劃之最長公共子串行 最長公共子串
題目 如果字串1的所有字元按其在字串中的順序出現在另外乙個字串2中,則字串1稱之為字串2的子串行。注意,並不要求子子串行 字串1 的字元必須連續出現在字串2中。請編寫乙個函式,輸入兩個字串,求它們的最長公共子串,並列印出最長公共子串行。例如 輸入兩個字串bdcaba和abcbdab,字串bcba和b...
動態規劃 最長公共子串行和最長公共子串
我們首先需要搞清楚以下兩個概念 最長公共子串行 vs 最長公共子串 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。問題描述 給定兩個字串,求解這兩個字串的最長公共子串行 longest common sequence 比如字串1 bdcaba 字串2 ab...