You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

最长公共子串递归记忆化代码测试用例失败问题排查与修正

修正最长公共子串的递归记忆化实现

首先明确:最长公共子串是连续的字符序列,和子序列逻辑不同。你的迭代DP能正常工作,说明状态转移逻辑是对的,递归记忆化的问题大概率出在状态定义、记忆化缓存的使用或者递归流程上。

常见递归记忆化错误原因

  • 错误地将记忆化状态存储全局最大值,而非以当前位置结尾的公共子串长度
  • 边界条件处理遗漏(比如其中一个字符串遍历完时,长度为0)
  • 递归过程中没有正确传递或更新全局最长长度
  • 重复递归调用导致的性能问题(甚至超时)

修正后的递归记忆化C++代码

假设你的迭代DP代码是基于二维数组dp[i][j]表示以s1[i-1]和s2[j-1]结尾的最长公共子串长度,状态转移为:

if (s1[i-1] == s2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = 0;

对应的递归记忆化实现如下:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

// 记忆化缓存,dp[i][j]表示以s1[i]和s2[j]结尾的最长公共子串长度
vector<vector<int>> memo;
int max_len = 0;

int dfs(const string& s1, const string& s2, int i, int j) {
    // 边界条件:遍历到字符串开头之前,返回0
    if (i < 0 || j < 0) return 0;
    
    // 如果已经计算过当前状态,直接返回缓存值
    if (memo[i][j] != -1) return memo[i][j];
    
    int current = 0;
    if (s1[i] == s2[j]) {
        // 当前字符匹配,递归计算前一个位置的结果+1
        current = dfs(s1, s2, i-1, j-1) + 1;
        // 更新全局最长长度
        max_len = max(max_len, current);
    } else {
        // 当前字符不匹配,当前长度为0,同时需要递归检查两个方向(因为最长子串可能在其他位置)
        dfs(s1, s2, i-1, j);
        dfs(s1, s2, i, j-1);
        current = 0;
    }
    
    // 缓存当前状态的结果
    memo[i][j] = current;
    return current;
}

int longestCommonSubstring(const string& s1, const string& s2) {
    int n = s1.size();
    int m = s2.size();
    max_len = 0;
    // 初始化记忆化数组,-1表示未计算
    memo.assign(n, vector<int>(m, -1));
    // 从两个字符串的末尾开始递归
    dfs(s1, s2, n-1, m-1);
    return max_len;
}

int main() {
    int n, m;
    cin >> n >> m;
    string s1, s2;
    cin >> s1 >> s2;
    cout << longestCommonSubstring(s1, s2) << endl;
    return 0;
}

关键修正点说明

  1. 记忆化状态定义:memo[i][j]严格对应迭代DP中的dp[i+1][j+1],存储以s1[i]和s2[j]结尾的最长公共子串长度,而非全局最大值,确保缓存能被重复利用。
  2. 边界处理:当i<0或j<0(即超出字符串范围)时,直接返回0,符合迭代DP中dp[0][*]和dp[*][0]为0的逻辑。
  3. 不匹配时的递归:即使当前字符不匹配,仍需递归检查s1[i-1]与s2[j]、s1[i]与s2[j-1]的情况,避免遗漏其他位置的公共子串。
  4. 全局最大值跟踪:在每次匹配成功时更新max_len,确保能捕获到所有可能的最长子串长度。

针对你的测试用例验证

对于输入:

17 60
KXCGMTMVVGFQQWSPD
JXZADDUKVLQPKUZJZHWSUTPCAFSYAIBJHAMMEGWBTPQELRNKBLDXGUZGCSEC

修正后的递归代码会正确计算出最长公共子串的长度,不会出现之前的失败情况。

内容的提问来源于stack exchange,提问作者Prashant Rai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 15:23:23