20天拿下华为OD笔试之【DP】2023Q1A-寻找重复代码【闭着眼睛学数理化】全网注释最详细分类最全的华为OD真题题解

【DP】2023Q1A-寻找重复代码

题目描述与示例

题目

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

注意子串是连续的

输入

输入的参数text1text2分别表示两行代码

输出

输出任一最长公共子串。

示例一

输入

hello123world
hello123abc4

输出

hello123

示例二

输入

private_void_method
public_void_method

输出

_void_method

示例三

输入

hiworld
hiweb

输出

hiw

解题思路

注意:本题和LC718. 最长重复子数组几乎完全一致。唯一区别在于,本题要计算的不是最长公共子串的长度,而是要输出最长公共子串本身

这是一个典型的dp问题。我们考虑动态规划三部曲:

  1. dp数组的含义是什么?
  • dp数组是一个大小为(N+1)*(M+1)的二维矩阵,dp[i][j]表示 text1i 个元素和 text2j 个元素的公共的、长度最长的连续子串的长度。
  1. 动态转移方程是什么?
  • 如果发现 text1 的当前元素,即位置为 i-1 的元素,与 text2 的当前元素即位置为 j-1 的元素**相同。**此时,找到了一个公共元素,公共的、长度最长的子串的长度加 1
if text1[i-1] == text2[j-1]:
    dp[i][j] = dp[i - 1][j - 1] + 1
  1. dp数组如何初始化?
  • dp[0][0] 表示 text10 个元素和 text20 个元素的公共的、长度最长的子串的长度,此时公共的、长度最长的子串的长度为 0
  • text1 或者 text2 没有字符时,公共的、长度最长的子串的长度都为 0
dp = [[0] * (n + 1) for _ in range(m + 1)]

dp[0][0] = 0

for i in range(1, m+1):
    dp[i][0] = 0

for j in range(1, n+1):
    dp[0][j] = 0

考虑完上述问题后,代码其实呼之欲出了。

代码

# 题目:2023Q1A-寻找重复代码
# 分值:100
# 作者:闭着眼睛学数理化
# 算法:动态规划(LCS问题)
# 代码看不懂的地方,请直接在群上提问


text1 = input()
text2 = input()

# 获取 text1 的长度
m = len(text1)

# 获取 text2 的长度
n = len(text2)



# 设置数组 dp,用来存储 text1 和 text2 公共的、长度最长的子串的长度
# dp[0][0] 表示 text1 前 0 个元素和 text2 前 0 个元素的公共的、长度最长的子串的长度
# dp[2][3] 表示 text1 前 2 个元素和 text2 前 3 个元素的公共的、长度最长的子串的长度
# dp[i][j] 表示 text1 前 i 个元素和 text2 前 j 个元素的公共的、长度最长的子串的长度
# 前 i 个元素的区间为 [0, i-1]
# dp[m][n] 表示 text1 前 m 个元素和 text2 前 n 个元素的公共的、长度最长的子串的长度
# 前 m 个元素的表示区间为 [0, m],前 n 个元素的表示区间为 [0, n]
# 因此,dp 数组的长度为 m + 1 和 n + 1
dp = [[0] * (n + 1) for _ in range(m + 1)]

# maxLength 表示 dp 数组中的最大值
maxLength = 0

# 初始化答案变量为空串
ans = ""

# 1. 初始化dp数组
# dp[0][0] 表示 text1 前 0 个元素和 text2 前 0 个元素的公共的、长度最长的子串的长度
# text1 text2 也没有元素
# 因此,公共的、长度最长的子串的长度为 0
dp[0][0] = 0

# text1 没有元素 或者 text2 没有字符时,公共的、长度最长的子串的长度都为 0
for i in range(1, m+1):
    dp[i][0] = 0

for j in range(1, n+1):
    dp[0][j] = 0

# i 从 1 开始,直到 m 位置,遍历 text1 的前 i 个元素
for i in range(1, m+1):
    # j 从 1 开始,直到 n 位置,遍历 text2 的前 j 个元素
    for j in range(1, n+1):
        
        # 2. 动态转移方程
        # 如果发现 text1 的当前元素,即位置为 i - 1 的元素
        # 与 text2 的当前元素,即位置为 j - 1 的元素【相同】
        # 此时,找到了一个公共元素,公共的、长度最长的子串的长度加 1
        if  text1[i - 1] == text2[j - 1]:

            # dp[i][j] 表示 text1 前 i 个元素和 text2 前 j 个元素的公共的、长度最长的子串的长度
            # dp[i - 1][j - 1] 表示 text1 前 i - 1 个元素和 text2 前 j - 1 个元素的公共的、长度最长的子串的长度
            dp[i][j] = dp[i - 1][j - 1] + 1

            # 更新最长的子串的长度
            if maxLength < dp[i][j]:
                maxLength = dp[i][j]
                # 最长子串长度为maxLength,对于text1而言,
                # 当前结束位置为i,当前开始位置为i-maxLength
                # 这里换成text2[j-maxLength: j]也是一样的
                ans = text1[i-maxLength: i]

# 返回结果
print(ans)

时空复杂度

时间复杂度:O(MN)。dp过程需要经历双重循环。

空间复杂度:O(MN)。二维dp数组所占据的空间。

MN分别为text1text2的长度。

华为OD算法冲刺训练

  • 华为OD算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 30+天陪伴式学习,20+直播课时,300+动画图解视频,200+LeetCode经典题,100+华为OD真题,还有简历修改与模拟面试将为你解锁

  • 可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 sheepvipvip了解更多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值