最长公共字序列
最長公共子序列,英文縮寫為LCS(Longest?Common?Subsequence)。
定義:一個序列?S?,如果分別是兩個或多個已知序列的子序列,且是所有符合此條件序列中最長的,則?S?稱為已知序列的最長公共子序列。
兩個字符串的最長子序列并不要求字符串連續,只要求有序,即統計兩個字符串有多少個重復的字符。用動態規劃的思路做。
設C[i][j]記錄以X[i]為結尾的字符串與Y[j]為結尾的字符串的LCS?的長度,分兩組情況考慮:
1)X[i]?==?Y[j],則
C[i][j]的結果可以根據C的定義通過C[i-1][j-1],得到
2)X[i]?/=?Y[j],則
轉化為C[i][j-1]和C[i-1][j]的結果,
具體公式如下
?
如下是具體的實現
int LongestCommonLength(const std::string& first, const std::string& last) {const size_t first_size = first.size();const size_t last_size = last.size();if (!first_size || !last_size ) {return 0;}// 用空間換時間size_t cost_map[first_size + 1][last_size + 1];memset(cost_map, 0, sizeof(cost_map));size_t max_len = 0;for (int i = 1; i <= first_size; ++i ){for (int j = 1; j <= last_size ; ++j ) {if ((first[j-1] == last[i-1])) {cost_map[i][j]=cost_map[i-1][j-1]+1;putchar(first[j-1]);} else {cost_map[i][j] = std::max(cost_map[i][j-1],cost_map[i-1][j]);}if (max_len < cost_map[i][j]) {max_len = cost_map[i][j];}printf("%ld\t", cost_map[i][j]);} // end-forprintf("\n");}return? max_len;
}
程序代碼中,未來減少對j-1=0的判斷,對每一行多分配一個存儲單元。
遍歷cost_map可以求出具體的子序列,
代碼示例為
int k = max_len;int i = first_size;int j = last_size;while (k > 0) {if (cost_map[i][j] == cost_map[i-1][j]) {--i;} else if (cost_map[i][j] == cost_map[i][j-1]) {--j;} else {putchar(first[i-1]);--j, --i;--k;}}putchar('\n');putchar的順序為逆序,reverse一下即可。
如果不需要求公共子序列,C[i][j]其實只需要兩維即可,可以看到,每次只需要兩列即可,此方法在某一列很大的時候,比較好,具體實現為
int LongestCommonLength(const std::string& first, const std::string& last) {const size_t first_size = first.size();const size_t last_size = last.size();if (!first_size || !last_size ) {return 0;}size_t map_size = first_size + 1;size_t cost_map[map_size<<1];memset(cost_map, 0, sizeof(cost_map));size_t* prev_map = cost_map;size_t* next_map = &cost_map[map_size];size_t max_len = 0;int end_pos = 0;for (int i = 1; i <= last_size; ++i ){for (int j = 1; j <= first_size ; ++j ) {if ((first[j-1] == last[i-1])) {next_map[j] = prev_map[j-1] + 1;} else {next_map[j] = std::max(next_map[j-1], prev_map[j]);}if (max_len < next_map[j]) {max_len = next_map[j];end_pos = j;}printf("%ld\t", next_map[j]);} // end-for std::swap(prev_map, next_map); // prev clearprintf("\n");} // end-forreturn max_len; }?
?
?
轉載于:https://www.cnblogs.com/westfly/archive/2013/03/18/2967049.html
總結
- 上一篇: XCode 4.3 不使用新特性 适用低
- 下一篇: Oracle内部错误:ORA-00600