NeFut Logo NeFut
Admin Login

In-Depth Analysis of Multi-Sequence Dynamic Programming: Longest Common Subsequence and Edit Distance

Published at: 2026-05-27 09:17 Last updated: 2026-06-06 13:04
#C++ #Tutorial

Core Logic and Mathematical Principles

The essence of multi-sequence dynamic programming is to perform topological path searches within a state space constructed by multi-dimensional Cartesian products. This section focuses on the Longest Common Subsequence (LCS) and Edit Distance, two problems that illustrate the state evolution during the processes of "alignment" and "matching."

1. Longest Common Subsequence (LCS)

Given two sequences $A$ (length $N$) and $B$ (length $M$), we seek the length of their longest common subsequence. The core logic lies in determining the equality of the current end elements $A[i]$ and $B[j]$:

2. Edit Distance

Given two strings $A$ and $B$, we calculate the minimum number of operations required to convert $A$ into $B$ (allowing insertion, deletion, and substitution of characters). Geometrically, the edit distance can be viewed as the shortest path problem on a two-dimensional grid, moving from the top left corner $(0,0)$ to the bottom right corner $(N,M)$. Each type of operation corresponds to a displacement vector in the state space:


State Design and Algorithm Derivation

1. LCS State and Equation

$$f[i][j] = \begin{cases} f[i-1][j-1] + 1 & \text{if } A[i] == B[j] \\ \max(f[i-1][j], f[i][j-1]) & \text{if } A[i] \neq B[j] \end{cases}$$

2. Edit Distance State and Equation

$$f[i][j] = \min \begin{cases} f[i-1][j] + 1 & \text{(deletion operation)} \\ f[i][j-1] + 1 & \text{(insertion operation)} \\ f[i-1][j-1] + \text{cost} & \text{(substitution operation)} \end{cases}$$

where if $A[i] == B[j]$, then $\text{cost} = 0$, otherwise $\text{cost} = 1$.


C++ Standard Source Code (NOIP Style)

The following source code implements a naive $O(N \times M)$ algorithm for both the Longest Common Subsequence and Edit Distance in a single program.

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

const int MAXN = 2005; // For NOIP traditional 2D DP data range
int lcs_f[MAXN][MAXN];
int edit_f[MAXN][MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    string s1, s2;
    if (!(cin >> s1 >> s2)) return 0;

    int n = s1.length();
    int m = s2.length();

    // To conform to algorithm habits, convert string indices to start from 1
    string a = " " + s1;
    string b = " " + s2;

    // ==================== 1. Longest Common Subsequence (LCS) ====================
    // Explicitly assign boundary values (although global variables default to 0, engineering norms require explicit representation)
    for (int i = 0; i <= n; ++i) lcs_f[i][0] = 0;
    for (int j = 0; j <= m; ++j) lcs_f[0][j] = 0;

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (a[i] == b[j]) {
                lcs_f[i][j] = lcs_f[i - 1][j - 1] + 1; // Critical pitfall: this must not be confused with the max operation
            } else {
                lcs_f[i][j] = max(lcs_f[i - 1][j], lcs_f[i][j - 1]);
            }
        }
    }

    // ==================== 2. Edit Distance (Edit Distance) ====================
    // Boundary initialization: cost of converting empty string
    for (int i = 0; i <= n; ++i) edit_f[i][0] = i;
    for (int j = 0; j <= m; ++j) edit_f[0][j] = j;

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            int cost = (a[i] == b[j]) ? 0 : 1;

            // Take the minimum of three transformation vectors
            int del_op = edit_f[i - 1][j] + 1;
            int ins_op = edit_f[i][j - 1] + 1;
            int rep_op = edit_f[i - 1][j - 1] + cost;

            edit_f[i][j] = min({del_op, ins_op, rep_op});
        }
    }

    cout << "LCS: " << lcs_f[n][m] << "\n";
    cout << "Edit Distance: " << edit_f[n][m] << "\n";

    return 0;
}

NOIP Practical Pitfall Guide

1. String Index and DP State Index Misalignment

2. Ignoring Replacement Cost When $A[i] == B[j]$ in Edit Distance


Classic NOIP/Luogu Problems

1. Luogu P2758 Edit Distance

2. Luogu P1156 Garbage Trap

  1. To stack: $f[i][j + h_i] = \max(f[i][j + h_i], f[i-1][j] - (t_i - t_{i-1}))$. If $j + h_i \ge D$, then output $t_i$ and terminate the program.
  2. To eat: $f[i][j] = \max(f[i][j], f[i-1][j] - (t_i - t_{i-1}) + f_i)$. If all garbage is processed and Carmen still cannot reach a height of $\ge D$, the global maximum survival time is the maximum span that the state with height 0 can sustain.
Original Source: local://14.2

[h] Back to Home