問題:
求兩字串行的最長公共字元子串行。
(這裡注意子串行和子串的區別,子串行可以是從原字串中取出一部分元素重新拼接而成的字串,但取出的元素之間的前後關係要與原字串一致;而子串則必須是連續的。如」adf」是」abcdef」的子串行,而不是子串。)
分析與解法:
設序列x=和y=的最長公共子串行為z= ,則
若xm-1=yn-1,則zk-1=xm-1=yn-1,且是和的最長公共子串行。
若xm-1≠yn-1且zk-1≠xm-1,則 是和最長公共子串行。
若xm-1≠yn-1且zk-1≠yn-1,則是和的最長公共子串行。
使用動態規劃的方法,將問題分為兩個子問題。
引進二維陣列c和b,用c[i][j]記錄x[i]與y[j] 的最長子序列的長度,b[i][j]記錄c[i][j]是通過哪乙個子問題的值求得的,以決定搜尋的方向。最後還要用回溯的方法把最長子串輸出出來。
遞推公式如下,
**如下,
#include
#define maxsize 50
using
namespace
std;
/*計算字串的最長子序列的長度*/
void lcs(char *x, char *y, int x_len, int y_len, int c[maxsize], int b[maxsize])
else
if(c[i][j - 1] <= c[i - 1][j])
else}}
}/*輸出最長子序列*/
void showlcs(int i, int j, int b[maxsize], char *x)
else
if(b[i][j] == -1)
showlcs(i - 1, j, b, x);
else
showlcs(i, j - 1, b, x);
}/*測試*/
int main(void)
借助圖表理解搜尋和輸出方式,
「左上」對應」i-1, j-1」,記作」0」「上」對應」i-1, j」,記作」-1」
「左」對應」i, j-1」,記作」1」
求最長公共子串行的時間複雜度是o(mn)。
由於每次呼叫至少向上或向左(或向上向左同時)移動一步,故最多呼叫(m + n)次就會遇到i = 0或j = 0的情況,此時開始返回。返回時與遞迴呼叫時方向相反,步數相同,故回溯列印最長公共子串行的時間複雜度是o(m+n)。
文章參考以下博文:
求最長公共子串行
字串行的子串行是指從給定字串行中隨意地 不一定連續 去掉若干個字元 可能乙個也不去掉 後所形成的字串行。令給定的字串行 x x0,x1,xm 1 序列 y y0,y1,yk 1 是 x 的子串行,存在 x的乙個嚴格遞增下標序列 i1,ik 1 使得對所有的 j 0,1,k 1 有 xij yj 例如...
求最長公共子串行和最長公共子串
輸入描述 輸入為兩行字串 可能包含空格 長度均小於等於50。輸出描述 輸出為乙個整數,表示最長公共連續子串的長度。輸入例子 abcde abgde 輸出例子 2題解 例如 str1 abcde str2 abgde matrix 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0...
求最長公共子串行本身
題目詳情請見 求字串的最長公共子串行 在上題求出子串行長度基礎上,我們要求出子串行本身長什麼樣 思路 在求最大長度的時候,我把當前最大長度的 記下來,用path陣列儲存 1 當前string1 i string2 j 2 當前string i string2 j 並且dp i 1 j dp i j ...