演算法課考了乙個最長公共子串行,考傻了。原題如下:
乙個序列s,若分別是兩個或多個已經序列的子串行,且是所有符合條件的序列中最長的,則s稱為已知序列的最長公共子串行。
比如和序列的最長公共子串行是。利用動態規劃法設計演算法求最長公共子串行問題。
當時很納悶,公共子串行為什麼不是連續的,即在中並不連續啊,琢磨了半天還是沒有解出。
後來經查詢:連續的是公共子串,而公共子串行只要保證順序不變即可,不要求連續。
假設有a,b兩個序列,lena = len(a),lenb = len(b);乙個輔助矩陣c,大小c[lena + 1][lenb + 1]。
上面的遞推公式很容易理解:當xi = yj 時,公共子串行長度加1。如果xi != yj,這時,自然而然我們想到公共子串行長度
不變,等於前乙個的長度。
假設xi與yj處於當前位置,xi != yj,那麼可以認為序列和序列的最長公共子串行為序列與序列的
最長公共子串行;當然,也可以認為是與的最長公共子串行。那麼我們求乙個最長的,認為是與最長
公共子串行。這樣,c[lena][lenb]即為二個序列的最長公共子串行的長度值。
現在需要另外乙個陣列,我把它稱作路徑陣列,記錄最長公共子串行的產生過程。便於取得最長公共子串行。
當遇到左上箭頭時,說明c[i][j] = c[i-1][j-1] + 1獲得的,即若此時最長公共子串行為ai、 bj,則下乙個公共子串行從ai-1, bj-1中取得。
當遇到上箭頭,對比於c[i][j] = c[i-1][j-1] + 1,說明c[i][j] = c[i-1][j],說明最長公共子串行ai、bj是通過ai-1,bj獲得的。
當遇到左箭頭,說明c[i][j] = c[i][j-1],最長公共子串行ai,bj是通過ai,bj-1獲得的。
其實很好理解,左上箭頭,i與j同時減1;左箭頭,在上圖中,即i不變,j減1;而上箭頭,j不變,i減1。
**:
const int leftup = 1;
const int up = 2;
const int left = 3;
void print(char *x, int **path, int i, int j)
else if(path[i][j] == up)
else }
void lcs_imp(char *x, char *y, int lenx, int leny, int **c, int **path)
for(int j = 0; j < leny + 1; j++)
for(int i = 1; i < lenx + 1; i++)
else
else
}} }}
int lcs(char *x, char *y, int lenx, int leny)
delete c;
delete path;
return len;
}
**調優:
可以進一步優化,省略路徑陣列。二維陣列c中的遞推關係很容易推得最長公共序列的產生過程。
最長公共子串行ai,bj,如果c[i][j] = c[i-1][j-1] + 1,則說明ai,bj是通過ai-1,bj-1獲得的。
只需陣列c,即可推斷產生序列。
void printlcs(char *x, char *y, int **c, int i, int j)
else if(c[i-1][j] > c[i][j-1])
else }
//使用
//printlcs(x, y, c, lenx, leny)
最長公共子串行 最長公共子串
1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...
最長公共子串行 最長公共子串
1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...
最長公共子串 最長公共子串行
子串要求連續 子串行不要求連續 之前的做法是dp求子序列 include include include using namespace std const int inf 0x3f3f3f3f const int mod 1000000007 string s1,s2 int dp 1010 10...