1、解题思路

  1. 动态规划:定义 dp[i][j] 为 str1 的前 i 个字符和 str2 的前 j 个字符的最长公共子串的长度。递推关系: 如果 str1[i-1] == str2[j-1],则 dp[i][j] = dp[i-1][j-1] + 1。否则,dp[i][j] = 0。初始条件:dp[0][j] = 0 和 dp[i][0] = 0(表示空字符串的公共子串长度为 0)。
  2. 记录最大值和位置:在填充 dp 表格的同时,记录最大长度和对应的位置。
  3. 反向构造子串:根据记录的最大长度和位置,从 str1 或 str2 中提取最长公共子串。

2、代码实现

C++
#include <vector>
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * longest common substring
     * @param str1 string字符串 the string
     * @param str2 string字符串 the string
     * @return string字符串
     */
    string LCS(string str1, string str2) {
        // write code here
        int m = str1.size(), n = str2.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); // 空间 O(m × n)
        int max_len = 0, pos = 0;
        for (int i = 1; i <= m; ++i) {  // 时间 O(m × n)
            for (int j = 1; j <= n; ++j) {
                if (str1[i - 1] == str2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    if (dp[i][j] > max_len) {
                        max_len = dp[i][j];
                        pos = i - 1;
                    }
                }
            }
        }
        if (max_len == 0) {
            return "-1";
        }
        return str1.substr(pos - max_len + 1, max_len);
    }
};

Java
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * longest common substring
     * @param str1 string字符串 the string
     * @param str2 string字符串 the string
     * @return string字符串
     */
    public String LCS (String str1, String str2) {
        // write code here
        int m = str1.length(), n = str2.length();
        int[][] dp = new int[m + 1][n + 1]; // 空间 O(m × n)
        int max_len = 0, pos = 0;
        for (int i = 1; i <= m; ++i) { // 时间 O(m × n)
            for (int j = 1; j <= n; ++j) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    if (dp[i][j] > max_len) {
                        max_len = dp[i][j];
                        pos = i - 1;
                    }
                } else {
                    dp[i][j] = 0;
                }
            }
        }
        if (max_len == 0) return "-1";
        return str1.substring(pos - max_len + 1, pos + 1);
    }
}

3、复杂度分析

  • 时间复杂度:O(m × n),其中 mn 分别是 str1str2 的长度。
  • 空间复杂度:O(m × n),用于存储 dp 表格。