最长公共子串

📘 题目描述

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

💡 解题思路

🔢 状态定义

  • $f_{i,j}$ 表示字符串 $s$ 以 $i$ 结尾和字符串 $t$ 以 $j$ 结尾的最长公共子串长度。

🔁 状态转移

  • 如果 $s[i] = t[j]$,则 $f_{i,j} = f_{i-1,j-1} + 1$。
  • 否则,$f_{i,j} = 0$。这意味着同时结尾无法形成公共子串,因为此时 $s[i]\not= t[j]$。

综上:

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

🟡 初始化:

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

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

✅ 统计答案

  • $ans=\max(f_{1,1},f_{1,2},\ldots,f_{1,m},\ldots,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;
        }
        ans = max(ans, f[i][j]);
    }
}