(A卷,100分)- 查找重复代码(Java & JS & Python)

题目描述

小明负责维护项目下的代码,需要查找出重复代码,用以支撑后续的代码优化,请你帮助小明找出重复的代码。
重复代码查找方法:以字符串形式给定两行代码(字符串长度 1 < length <= 100,由英文字母、数字和空格组成),找出两行代码中的最长公共子串。
注:如果不存在公共子串,返回空字符串

输入描述

输入的参数text1, text2分别表示两行代码

输出描述

输出任一最长公共子串

用例

输入 hello123world
hello123abc4
输出 hello123
说明
输入 private_void_method
public_void_method
输出 _void_method
说明
输入 hiworld
hiweb
输出 hiw
说明

题目解析

本题可以使用动态规划求解,下面解释下本题动态规划解题思路。

动态规划,一般是将大问题分解为规模更小的相同的子问题,如果子问题依旧很难求解,则继续分解,直到规模小到子问题可以被轻松求解。

比如上面求两个字符串的最长公共子串,如果两个字符串很长,那么我们将很难一下子发现最长公共子串,那么我们可以只看两个字符串的部分范围,比如字符串str1,只看0~i范围,字符串str2,只看0~j范围,然后求解str1的0~i范围和str2的0~j范围的最长公共子串,最简单就是str1的0~0范围,即空串,和任意str2范围的最长公共子串都是空串,接着我们可以慢慢扩大str1的范围。

可能上面说的还比较抽象,我们可以用一个二维数组dp来描述上面逻辑。

dp[i][j] 表示的是,str1的0~i范围  和  str2的0~j范围   的公共子串的长度

初始时,我们可以得出如下二维矩阵

 即str1取0~0,即空串时,和任意str2范围的公共子串的长度都是0。

同理,str2取0~0,即空串时,和任意str1范围的公共子串的长度都是0。

接下来, str1取0~1范围(即h),和str2取0~1范围(即h),的公共子串其实就是h,因此长度为1。如下图所示

但是上面公共子串长度求解,也可以看成是,str1扩大范围新增的h,和str2扩大范围新增的h相同,因此出现了公共子串,那么就相当于在str1未扩大范围前(即空串时),和str2未扩大范围前(即空串时),的公共子串长度的基础上+1。

即:dp[1][1] = dp[0][0] + 1

进一步分析,其实可得出状态转移方程:

if(str1[i] === str2[j])  dp[i][j] = dp[i-1][j-1] + 1

再接下来, str1还是取0~1范围(即h),和str2取0~2范围(即he),

此时str1还是相当于新增h,而str2相当于新增e,新增部分不相同,所以此处没有增长前面基础上得到的公共子串的长度。

那么此时相当于 if(str1[i] !== str2[j])  dp[i][j] = dp[i-1][j-1] + 0,

但是这种思路是错误的,因为当str1,str2新增范围字符不同时,意味着公共子串的中断,我们应该将此时的dp[i][j]置为0,这样才能防止dp[i+1][j+1]对应的字符相同时,继承前面的公共子串长度。

请看下面错误例子

 正确例子应该是

因此正确的动态规划状态转移方程是:

  • dp[i][0] = 0
  • dp[0][j] = 0
  • if(str1[i] === str2[j])  dp[i][j] = dp[i-1][j-1] + 1   else dp[i][j] = 0

但是此题并不是让我们求解最长的公共子串的长度,而是求出任一最长公共子串。因此我们可以在遍历求解上面二维矩阵每一个元素时,记录下公共子串最大的长度值,比如下面例子中,求解到黄色元素dp[2][2]时,得到了目前最大的公共子串长度2,

因此我们可以从任一维度来获取这个公共子串,比如从列维度,相当于 str2.slice( j – maxLen, j),其中j对应dp[i][j]中的j。maxLen=dp[i][j]。

 

JavaScript算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines = [];
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 2) {
    const str1 = lines[0];
    const str2 = lines[1];
    console.log(getResult(str1, str2));
    lines.length = 0;
  }
});

function getResult(str1, str2) {
  const n = str1.length;
  const m = str2.length;

  const dp = new Array(n + 1).fill(0).map(() => new Array(m + 1).fill(0));

  let max = 0;
  let ans = "";

  for (let i = 1; i <= n; i++) {
    for (let j = 1; j <= m; j++) {
      if (str1[i - 1] === str2[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1] + 1;

        if (dp[i][j] > max) {
          max = dp[i][j];
          ans = str1.slice(i - max, i);
        }
      } else {
        dp[i][j] = 0;
      }
    }
  }

  return ans;
}

Java算法源码

import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    String str1 = sc.nextLine();
    String str2 = sc.nextLine();

    System.out.println(getResult(str1, str2));
  }

  public static String getResult(String str1, String str2) {
    int n = str1.length();
    int m = str2.length();

    int[][] dp = new int[n + 1][m + 1];

    int max = 0;
    String ans = "";

    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= m; j++) {
        if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
          dp[i][j] = dp[i - 1][j - 1] + 1;

          if (dp[i][j] > max) {
            max = dp[i][j];
            ans = str1.substring(i - max, i);
          }
        } else {
          dp[i][j] = 0;
        }
      }
    }

    return ans;
  }
}

Python算法源码

# 输入获取
str1 = input()
str2 = input()


# 算法入口
def getResult(str1, str2):
    n = len(str1)
    m = len(str2)

    dp = [[0 for i in range(m + 1)] for j in range(n + 1)]

    maxV = 0
    ans = ""

    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if str1[i - 1] == str2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1

                if dp[i][j] > maxV:
                    maxV = dp[i][j]
                    ans = str1[(i - maxV):i]
            else:
                dp[i][j] = 0

    return ans


# 算法调用
print(getResult(str1, str2))

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?