d231: 97北縣賽-2-基因序列密碼問題

Tags: l.c.s, sequence


出處:https://zerojudge.tw/ShowProblem?problemid=d231
提交:https://zerojudge.tw/Submissions?problemid=d231&account=allllllan123456


問題:給定兩個長度分別介於 $[1,50]$ 而且僅由 A、C、G、T 四個英文字母組成的字串,請求出它們的最長共同子序列?


解法:就很經典可以用 DP 解決的老問題,而且因為這題要把子序列印出來但 size 又不大,我就嘗試著把函式回傳值直接改成當下的最長子序列,寫起來也蠻簡潔漂亮,一般教科書不會這樣教的。


 1#include <bits/stdc++.h>
 2using namespace std;
 3
 4string str1, str2, dp[50][50];
 5
 6string lcs(int x, int y) {
 7    if (dp[x][y].length()) return dp[x][y];
 8    if (!x && !y) return (str1[x]==str2[y]) ? string{str1[x]} : "";
 9    if (!x) {
10        if (str1[x] == str2[y]) return dp[x][y] = str1[x];
11        return dp[x][y] = lcs(x, y-1);
12    }
13    if (!y) {
14        if (str1[x] == str2[y]) return dp[x][y] = str1[x];
15        return dp[x][y] = lcs(x-1, y);
16    }
17    if (str1[x] == str2[y]) return dp[x][y] = lcs(x-1, y-1) + str1[x];
18    string a = lcs(x-1, y), b = lcs(x, y-1);
19    return dp[x][y] = (a.length() > b.length()) ? a : b;
20}
21
22int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); // IO 優化
23    cin >> str1 >> str2;
24    string ans = lcs(str1.length()-1, str2.length()-1);
25    cout << (ans.length() ? ans : "E") << '\n';
26    return 0;
27}

no image