The longest sequence appearing (not necessarily contiguously) in both strings.

The recurrence

int lcs(const string& a, const string& b) {
    int n = a.size(), m = b.size();
    vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            dp[i][j] = (a[i-1] == b[j-1]) ? dp[i-1][j-1] + 1
                                          : max(dp[i-1][j], dp[i][j-1]);
    return dp[n][m];
}

time and space; space with a rolling array.

Reconstructing the subsequence

string reconstruct(const string& a, const string& b, vector<vector<int>>& dp) {
    string res;
    int i = a.size(), j = b.size();
    while (i > 0 && j > 0) {
        if (a[i-1] == b[j-1]) { res += a[i-1]; i--; j--; }
        else if (dp[i-1][j] >= dp[i][j-1]) i--;
        else j--;
    }
    reverse(res.begin(), res.end());
    return res;
}

Needs the full table. With only two rows, use Hirschberg’s algorithm — time, space, and it still produces the actual subsequence.

Beating

SituationMethodTime
Both strings are permutationsmap to indices, run LIS
One string has few distinct charactersHunt-Szymanski, = matching pairs
Small alphabet, need raw speedbit-parallel (Crochemore-Iliopoulos-Pinzon)
The answer is known to be short/longbanded DP around the diagonal

The permutation trick

If and are permutations of the same multiset with distinct elements, replace each element of by its position in . A common subsequence of the two is exactly an increasing subsequence of that new array. instead of .

Lower bound: no algorithm exists for general LCS unless the Strong Exponential Time Hypothesis fails. The quadratic barrier is real.

ProblemDifference
Longest common substring (contiguous)dp[i][j] = dp[i-1][j-1]+1 on match, 0 otherwise; or use a suffix automaton for
Edit distanceminimisation with insert/delete/replace
Shortest common supersequence
Longest palindromic subsequenceLCS of and
Minimum insertions to make a palindrome
LCS of strings — NP-hard in
Longest common increasing subsequence with a running maximum
Diff (Myers’ algorithm)LCS with an algorithm where is the edit distance — what git diff uses

The palindromic subsequence reduction is the most reused: LPS = LCS, so any LCS code solves palindrome problems for free.

Counting distinct LCS

Add a count array alongside the length array, being careful not to double-count when both dp[i-1][j] and dp[i][j-1] achieve the maximum — subtract dp[i-1][j-1]’s count by inclusion-exclusion when the characters differ and both branches tie.

See also: Edit Distance · LIS · Hirschberg