前面一篇博文動態規劃 矩陣連乘問題,學習了什麼是動態規劃,以及什麼時候該用動態規劃,總得來說就是:
當乙個問題可以被分成若干個子問題求解,且子問題可以優化子結構,存在子問題重複的時候,就可以使用動態子結構。
最長公共子串行的定義:
設 兩個序列分別為 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的最大公共...