問題描述:見演算法導論p208-p209
前提概念
給定乙個序列x = (x1, x2, ..., xm),對i = 0, 1, ..., m,記x的第i個字首為xi = (x1, x2, ..., xi),故xm = x,而x0是個空序列
乙個給定序列的子串行就是該序列去掉0個或多個元素(不一定連續),如bcdb是abcbdab的乙個子串行
基於以上定義,最長公共子串行(lcs)有如下性質:
設x = (x1, x2, ..., xm)和y = (y1, y2, ..., yn)為兩個序列,並設z = (z1, z2, ..., zk)為x和y的乙個lcs
以上性質說明
兩個序列的lcs也包含了兩個序列字首的乙個lcs,即lcs問題具有最優子結構
遞迴表示式
記c[i, j]為xi和yj的lcs的長度,則由上面給出的lcs的性質得如下遞迴表示式
自底向上的求解
由分析知,矩陣c中的任意元素c[i, j]的值只取決於其左方、上方以及左上方元素的值。因此,應對矩陣c按從上至下,從左至右的方向進行逐行遍歷求值。原問題最優解的值為c[m, n]
構造最優解
使用矩陣b記錄最優解的構造,其任意元素b[i, j]的值為列舉型,只取以下三個值
構造過程是這樣的:首先從b[m, n]處開始,沿著箭頭在**中追蹤下去,當在b[i, j]遇到left_up,即意味著xi = yi是乙個lcs元素,列印輸出並繼續跟蹤;若遇到left或up,則繼續按箭頭方向跟蹤,示意圖如下
構造過程應是遞迴的
**
#define left 1
#define up 2
#define left_up 3
void dp(char * x, char * y, int len1, int len2)
for(int i = 0; i < len1+1; i++)
else if(x[i-1] == y[j-1])和的lcs長度
c[i][j] = c[i-1][j-1]+1;
b[i][j] = left_up;
}else
else
}} }
printf("lcs(%d): ", c[len1][len2]);
print_lcs(x, y, len1, len2, b);
printf("\n");
}void print_lcs(char * x, char * y, int i, int j, int ** b)
else if(b[i][j] == up)
print_lcs(x, y, i-1, j, b);
else
print_lcs(x, y, i, j-1, b);
}}
最長公共子串行問題LCS
乙個給定序列的子串行是指在原序列順序不變的基礎上刪去若干元素後得到的序列。給定兩個序列x和y,當乙個序列z既是x的子串行又是y的子串行時,稱z序列為x和y 的公共子串行。例如,x a,b,c,b,d,a,b y b,d,c,a,b,a 則序列 b,c,a 是x和y的乙個公共子串行,但不是x和y的最長...
最長公共子串行 LCS 問題
前言 學習過的知識,只要不經常使用就會忘記,所以在此寫部落格,記錄下來,方便自己,也可能有利於他人。最長公共子串行 lcs 問題。1.什麼是最長公共子串行?最長公共子串行,英文縮寫為lcs longest common subsequence 其定義是,乙個序列 s 如果分別是兩個或多個已知序列的子...
最長公共子串行問題 LCS
最長公共子串行問題 lcs 問題 求兩字串行的最長公共字元子串行 問題描述 字串行的子串行是指從給定字串行中隨意地 不一定連續 去掉若干個字元 可能乙個也不去掉 後所形成的字串行。令給定的字串行x x0,x1 xm 1 序列y y0,y1 yk 1 是x 的子串行,存在x 的乙個嚴格遞增下標序列,i...