動態規劃 最長公共子串行問題

2021-07-07 08:16:59 字數 1996 閱讀 4547

最長公共子串行問題(longest-common-subsequence problem)簡稱lcs問題。題目為給定兩個序列x、y求它們的lcs(最長公共子串行),這裡的子串行z的定義為:z中的元素既在x中也在y中,並且他們在x、y中滿足嚴格的下標為乙個增序列(假設下標從左到右依次增大)。另外,不要求z中的元素在x、y中是連續的,比如當a = ,b = 時,可以有z = 。現在我們需要求的是lcs,即符合這種條件的最長的乙個公共子串行。

而lcs問題是一類動態規劃(dp:dynamic programming)問題 。其具有最優子結構性質,定義如下:

設序列 x = 和 y = 的乙個最長公共子串行 z = ,則:

1> 若 xm=yn,則 zk=xm=yn,且zk-1是xm-1和yn-1的最長公共子串行; 

2> 若 xm≠yn且 zk≠xm ,則 z是 xm-1和 y的最長公共子串行;

3> 若 xm≠yn且 zk≠yn ,則 z是 x和 yn-1的最長公共子串行;

其中xm-1=,yn-1=,zk-1=。

上面的結論很容易證明。

下面貼上演算法導論中的偽**(其中的陣列b可以不用理會,c用於儲存xm和yn的lcs):

源**如下(注意:我的源**中的n是序列x的長度,m是序列y的長度):

/*  計算lcs,動態規劃從前往後推算  */

#include #include #include #define n 1000

char x[n], y[n]; //序列x、y

int c[n][n]; //cij為xi和yj的最長公共子串行

int lcs(int n, int m); //計算最長公共子串行

void getanswer(int n, int m); //構建答案

int main()

return 0;

}int lcs(int n, int m)

}return c[n][m];

}void getanswer(int n, int m)

else if(c[n][m] == c[n-1][m])

getanswer(n-1, m);

else

getanswer(n, m-1);

}

另一種方法是從後面向前面推算,當然得到的答案也肯能不一樣,但一定是最長的:

/*  計算lcs,動態規劃從後往前推算  */

#include #include #include #define n 1000

char x[n], y[n]; //序列x、y

int c[n][n]; //cij為xi和yj的最長公共子串行

int lcs(int n, int m); //計算最長公共子串行

void getanswer(int x, int y, int n, int m); //構建答案

int main()

return 0;

}int lcs(int n, int m)

}return c[1][1];

}void getanswer(int x, int y, int n, int m)

else if(c[x][y] == c[x+1][y])

getanswer(x+1, y, n, m);

else

getanswer(x, y+1, n, m);

}

如有疏漏,請批評指正

最長公共子串行問題 動態規劃

給定兩個字串s1s2.sn和t1t2.tn。求出這兩個字串最長的公共子串行 輸入 abcicba abdkscab 輸出 abca 定義dp i j 為s1 si和t1 tj對應的lcs的長度 s1 si 1和t1 tj 1對應的公共子列有三種情況 當si 1 tj 1時,在s1 si和t1 tj的...

最長公共子串行問題(動態規劃)

time limit 1000ms memory limit 65536kb problem description 給定兩個序列x input 輸入資料有多組,每組有兩行 每行為乙個長度不超過500的字串 輸入全是大寫英文本母 a,z 表示序列x和y。output 每組輸出一行,表示所求得的最長公...

動態規劃 最長公共子串行問題

動態規劃d題 題目 include define n 500 includeint main 初始化首列陣列c的第1列是0 for j 0 j len2 j 初始化首行陣列c的第1行是0 for i 1 i len1 i 動態規劃 for j 1 j len2 j 比較x的第i個元素與y的第j個元素...