最长公共子序列 LCS

📘 题目描述

给定两个字符串 $s,t$,求出它们的最长公共子序列长度。字符串长度 $1\leq |s|,|t|\leq 2000$。

💡 解题思路

🔢 状态定义

  • $f_{i,j}$ 表示字符串 $s[1..i]$ 和字符串 $t[1..j]$ 的最长公共子序列长度。

🔁 状态转移

  • 如果 $s[i] = t[j]$,则 $f_{i,j} = f_{i-1,j-1} + 1$。
  • 否则,$f_{i,j} = max(f_{i-1,j}, f_{i,j-1})$。

综上:

\[ f_{i,j} = \begin{cases} f_{i-1,j-1} + 1, & \text{if } s[i] = t[j] \\ max(f_{i-1,j}, f_{i,j-1}), & \text{otherwise} \end{cases} \]

🟡 初始化:

初始化时,$f_{i,0} = 0$,$f_{0,j} = 0$。

  • 含义:当字符串 $s$ 为空时,最长公共子序列长度为 $0$。同理当 $t$ 为空时,最长公共子序列长度为 $0$。

✅ 统计答案

  • $ans=f_{n,m}$。

⏱️复杂度分析

  • 时间复杂度:$O(n\cdot m)$。
  • 空间复杂度:$O(n\cdot m)$。

✅ 代码实现

int n = s.size(), m = t.size();
s = " " + s, t = " " + t;
for (int i = 1; i <= n; i++)
{
    for (int j = 1; j <= m; j++)
    {
        if (s[i] == t[j])
        {
            f[i][j] = f[i - 1][j - 1] + 1;
        }
        else
        {
            f[i][j] = max(f[i - 1][j], f[i][j - 1]);
        }
    }
}