动态规划 最长公共子串

77 阅读1分钟

题目

给定两个字符串,求两个字符串的最长公共子串

  • 遍历模型为,两个公共子串如果有,那么最后一位一定相等,所以遍历两个字符串的所有子串,如果最后一位相等,那么就看双方前面位置的字符串是否相等,如果最后一位不相等那么公共子串一定为0
  • 所以dp数组为 dp[i][j],以i位置结尾的字符串1和以j位置结尾的字符串2,如果相等取 dp[i-1][j-1]+1,如果不等为0
  • 对于第一行和第一列,只有相等时为1,不等为0

ca1934455f344849e5722a1df0c07aba.png

function process(str1, str2) {
  let res = 0,
    dp = [],
    row = str1.length,
    col = str2.length;

  // 第一列和第一行不想等则为0,相等为1
  for (let i = 0; i < row; i++) {
    if (str2[0] === str1[i]) {
      dp[0][i] = 1;
      if (res < dp[0][i]) {
        res = dp[0][i];
      }
    } else {
      dp[0][i] = 0;
    }
  }

  for (let i = 0; i < col; i++) {
    if (str1[0] === str2[i]) {
      dp[i][0] = 1;
      if (res < dp[0][i]) {
        res = dp[0][i];
      }
    } else {
      dp[0][i] = 0;
    }
  }

  for (let i = 1; i < row; i++) {
    for (let j = 1; j < col; j++) {
      // 以 i、j 结尾的字符不相等为 0,相等取 dp[i-1][j-1] 的值 +1
      if (str1[i] !== str2[j]) {
        dp[i][j] = 0;
      } else {
        dp[i][j] = dp[i - 1][j - 1] + 1;
        if (res < dp[0][i]) {
          res = dp[0][i];
        }
      }
    }
  }

  return res;
}