One relatively simple way would be to recover sequences from the LCS matrix. The following is the O (n ^ 2 * k + x * n) algorithm, where x is the size of the output (i.e., the number of common subsequences of length k). This is in C ++, but it is quite easy to translate it to C:
const int N = 100; int lcs[N][N]; set<tuple<string,int,int,int>> vis; string s1 = "AAGACC"; string s2 = "AGATAACCAGGAGCTGC"; void reconstruct(const string& res, int i, int j, int k) { tuple<string,int,int,int> st(res, i, j, k); if (vis.count(st)) return; vis.insert(st); if (lcs[i][j] < k) return; if (i == 0 && j == 0 && k == 0) { cout << res << endl; return; } if (i > 0) reconstruct(res, i-1, j, k); if (j > 0) reconstruct(res, i, j-1, k); if (i>0 && j>0 && s1[i-1] == s2[j-1]) reconstruct(string(1,s1[i-1]) + res, i-1, j-1, k-1); } int main() { lcs[0][0] = 0; for (int i = 0; i <= s1.size(); ++i) lcs[i][0] = 0; for (int j = 0; j <= s1.size(); ++j) lcs[0][j] = 0; for (int i = 0; i <= s1.size(); ++i) { for (int j = 0; j <= s2.size(); ++j) { if (i > 0) lcs[i][j] = max(lcs[i][j], lcs[i-1][j]); if (j > 0) lcs[i][j] = max(lcs[i][j], lcs[i][j-1]); if (i > 0 && j > 0 && s1[i-1] == s2[j-1]) lcs[i][j] = max(lcs[i][j], lcs[i-1][j-1] + 1); } } reconstruct("", s1.size(), s2.size(), 5); }
There should also be an O (n * (k + x)) method based on a slightly different DP approach: let f (i, k) be the minimal index j such that lcs (i, j)> = k. We have recurrence
f(i, 0) = 0 for all i f(i, k) = min{f(i-1, k), minimum j > f(i-1, k-1) such that s2[j] = s1[i]}
We can also reconstruct sequences of length k from the matrix f.