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

2021-07-25 04:09:08 字數 2067 閱讀 1335

前面一篇博文動態規劃 矩陣連乘問題,學習了什麼是動態規劃,以及什麼時候該用動態規劃,總得來說就是:

當乙個問題可以被分成若干個子問題求解,且子問題可以優化子結構,存在子問題重複的時候,就可以使用動態子結構。

最長公共子串行的定義:

設 兩個序列分別為 x = , y = ,他們的最長公共子串行為 z = ,那麼就存在下面這幾種情況:

如果xm == yn == zk , 那麼 z = 一定是 x = , y = 的最長公共子串行;

如果xm != yn, 且zk != xm, 那麼z = 是 x = , y = 的最長公共子串行;

如果xm != yn, 且zk != yn, 那麼z = 是 x = , y = 的最長公共子串行;

如果不太理解,可以具體代入。

這樣的話,當我們問題如果遇到xm == yn的情況下,就直接解決了乙個子問題,說明xm或者yn就是最長公共子串行中的最後乙個,接下來我們就只需要求x = , y = 的序列;當xm != yn的情況下,則需要解決兩個子問題,分別是zk != xm和 zk != yn的情況,然後取兩種情況分別所得的最長公共子串行的最大致。

概念如果有點模糊的話,我們來舉個例子:

1. 如果x = 「abcd」,y = 「acbd」,由於xm = 「d」 和 yn = 「d」相等,所以我們已經得出xy的最大公共子串行的最後乙個值是d;

2. 如果x = 「abdc」,y = 「acbd」,由於xm = 「c」和 yn = 「d」不相等,所以我們要解決x = 「abd」,y = 「acbd」和 x = 「abdc」,y = 「acb」兩個子問題,取兩個子問題中最長的公共子串行。

除了用c[i, j]來記錄i到j的最長公共子串行的長度,還要用乙個陣列b[i][j]來記錄每乙個子問題的前乙個子問題,然後回溯輸出最長公共子串行。

(圖從網上摘得,如果作者不允許使用,請告知)

#include

#include

using

namespace

std;

const

int maxlen = 10000;

int b[maxlen][maxlen];

int c[maxlen][maxlen];

void lcslength(char* x, char* y, int m, int n)

for(i = 1; i <= n; i++)

for(i = 1; i <= m; i++)else

if(c[i-1][j] > c[i][j-1])else}}

//直**看c陣列和b陣列

for(i = 0; i < m; i++)

printf("\n");

}printf("\n");

for(i = 0; i < m; i++)

printf("\n");

}printf("\n");

}void printlcs(char *x, int i, int j)

else

if(b[i][j] == 1)

printlcs(x, i-1, j);

else

printlcs(x, i, j-1);

}int main();

char y[maxlen] = ;

int m = strlen(x);

int n = strlen(y);

lcslength(x, y, m, n);

printlcs(x, m, n);

return

0;}

結果如下:

動態規劃 公共子串行

公共子串行 總時間限制 1000ms 記憶體限制 65536kb 描述 我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行當且僅當存在 嚴格上公升 的序列 i1,i2,ik 使得對j 1,2,k,有xij zj。比如z a,b,f,c 是x a,b,c,f,b,c 的子串行。現在給...

動態規劃 公共子串行

輸入兩個字串,輸出其中最長的公共子串行。狀態 有兩個字串,就要有兩個控制狀態的變數a i j 第乙個字串的第i個字元,第二個字串的第j個字元。b i 是第乙個字串,c i 是第二個字串。子問題 求第乙個字串的第i個字元和第二個字串的第j個字元是不是相等。狀態轉移方程 第乙個字串的第i個字元和第二個字...

動態規劃 公共子串行

描述 我們稱序列z z 1,z 2,z k 是序列x x 1,x 2,x m 的子串行當且僅當存在嚴格上公升的序列 i 1,i 2,i k 使得對j 1,2,k,有x ij z j。比如z a,b,f,c 是x a,b,c,f,b,c 的子串行。現在給出兩個序列x和y,你的任務是找到x和y的最大公共...