【算法进阶2-动态规划】最长公共子序列、欧几里得算法-分数、RSA算法-密码于加密

本文主要是介绍【算法进阶2-动态规划】最长公共子序列、欧几里得算法-分数、RSA算法-密码于加密,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 最长公共子序列
2 欧几里得算法
2.1 欧几里得算法-分数
3 RSA算法-密码于加密

1 最长公共子序列

在这里插入图片描述

-个序列的子序列是在该序列中删去若干元素后得 到的序列。
例:“ABCD”和“BDF”都是“ABCDEFG”的子序列最长公共子序列(LCS)问题:给定两个序列X和Y,求X和Y长度最大的公共子序列。
例:X="ABBCBDE" Y="DBBCDB" LCS(X,Y)="BBCD"应用场景:字符串相似度比对

在这里插入图片描述

from typing import Tupledef lcs_length(x: str, y: str) -> int:"""计算两个字符串的最长公共子序列 (LCS) 的长度。使用动态规划方法解决LCS问题。LCS问题是指在两个字符串中找到一个最长的子序列,使得这个子序列在两个字符串中都出现,并且保持其相对顺序不变。:param x: 第一个字符串:param y: 第二个字符串:return: 返回两个字符串的最长公共子序列的长度"""m = len(x)  # 第一个字符串的长度n = len(y)  # 第二个字符串的长度# 创建一个 (m+1) x (n+1) 的二维列表 c,用于存储子问题的解# c[i][j] 表示字符串 x 的前 i 个字符和字符串 y 的前 j 个字符的最长公共子序列的长度c = [[0 for _ in range(n + 1)] for _ in range(m + 1)]# 填充二维列表 cfor i in range(1, m + 1):  # 遍历字符串 x 的每个字符for j in range(1, n + 1):  # 遍历字符串 y 的每个字符if x[i - 1] == y[j - 1]:  # 如果 x 的第 i 个字符等于 y 的第 j 个字符# 如果字符匹配,当前最长公共子序列的长度是左上角的值 + 1c[i][j] = c[i - 1][j - 1] + 1else:# 如果字符不匹配,取上方或左方的最大值c[i][j] = max(c[i - 1][j], c[i][j - 1])# 打印二维列表 c 的值(用于调试)for _ in c:print('列表的值是:', _)# 返回最长公共子序列的长度,即 c[m][n]return c[m][n]# print(lcs_length("ABCBDAB", "BDCABA"))  # 4# 列表的值是: [0, 0, 0, 0, 0, 0, 0]
# 列表的值是: [0, 0, 0, 0, 1, 1, 1]
# 列表的值是: [0, 1, 1, 1, 1, 2, 2]
# 列表的值是: [0, 1, 1, 2, 2, 2, 2]
# 列表的值是: [0, 1, 1, 2, 2, 3, 3]
# 列表的值是: [0, 1, 2, 2, 2, 3, 3]
# 列表的值是: [0, 1, 2, 2, 3, 3, 4]
# 列表的值是: [0, 1, 2, 2, 3, 4, 4]def lcs(x: str, y: str) -> Tuple[int, list]:"""计算两个字符串的最长公共子序列 (LCS) 的长度,并生成动态规划表。使用动态规划方法求解两个字符串的最长公共子序列问题,并返回长度以及记录方向的表,用于后续的LCS路径恢复。:param x: 第一个字符串:param y: 第二个字符串:return: 返回一个元组,包含两个元素:- LCS的长度- 动态规划表 b,其中 b[i][j] 表示到达位置 (i, j) 时的方向"""m = len(x)  # 第一个字符串的长度n = len(y)  # 第二个字符串的长度# 创建一个 (m+1) x (n+1) 的二维列表 c,用于存储子问题的解# c[i][j] 表示字符串 x 的前 i 个字符和字符串 y 的前 j 个字符的最长公共子序列的长度c = [[0 for _ in range(n + 1)] for _ in range(m + 1)]# 创建一个 (m+1) x (n+1) 的二维列表 b,用于记录方向# b[i][j] 表示到达位置 (i, j) 时的方向# "←" 表示来自左上方(匹配),# "↑" 表示来自上方(不匹配,向上移动),# "↖" 表示来自左方(不匹配,向左移动)b = [['*' for _ in range(n + 1)] for _ in range(m + 1)]# 填充二维列表 c 和 bfor i in range(1, m + 1):for j in range(1, n + 1):if x[i - 1] == y[j - 1]:  # 如果 x 的第 i 个字符等于 y 的第 j 个字符# 如果字符匹配,当前最长公共子序列的长度是左上角的值 + 1c[i][j] = c[i - 1][j - 1] + 1b[i][j] = "←"  # 方向来自于左上方(匹配)elif c[i - 1][j] > c[i][j - 1]:  # 如果来自上方的值大于来自左方的值# 如果上方的值更大,选择上方的值c[i][j] = c[i - 1][j]b[i][j] = "↑"  # 方向来自于上方(不匹配,向上移动)else:# 如果左方的值更大或相等,选择左方的值c[i][j] = c[i][j - 1]b[i][j] = "↖"  # 方向来自于左方(不匹配,向左移动)# 返回最长公共子序列的长度和方向记录表return c[m][n], bc, b = lcs("ABCBDAB", "BDCABA")
for _ in b:print(_)# ['*', '*', '*', '*', '*', '*', '*']
# ['*', '↖', '↖', '↖', '←', '↖', '←']
# ['*', '←', '↖', '↖', '↖', '←', '↖']
# ['*', '↑', '↖', '←', '↖', '↖', '↖']
# ['*', '←', '↖', '↑', '↖', '←', '↖']
# ['*', '↑', '←', '↖', '↖', '↑', '↖']
# ['*', '↑', '↑', '↖', '←', '↖', '←']
# ['*', '←', '↑', '↖', '↑', '←', '↖']def lcs_traceback(x: str, y: str) -> str:"""根据动态规划表回溯,找出两个字符串的最长公共子序列 (LCS)。使用动态规划表 `b` 来回溯最长公共子序列的路径,并从结果表 `c` 中获取最长公共子序列的字符。最终返回最长公共子序列的字符串。:param x: 第一个字符串:param y: 第二个字符串:return: 返回两个字符串的最长公共子序列(LCS)的字符串表示"""# 调用 lcs 函数获取动态规划表 c 和方向记录表 bc, b = lcs(x, y)i = len(x)  # 初始化 i 为第一个字符串的长度j = len(y)  # 初始化 j 为第二个字符串的长度res = []  # 用于存储回溯得到的 LCS 字符# 根据方向记录表 b 从表的右下角开始回溯到左上角while i > 0 and j > 0:if b[i][j] == "←":# 如果方向来自于左上方(匹配),则当前字符是 LCS 的一部分res.append(x[i - 1])i -= 1  # 移动到前一个字符j -= 1  # 移动到前一个字符elif b[i][j] == "↑":# 如果方向来自于上方,则移动到上方的子问题i -= 1else:  # '↖'# 如果方向来自于左方,则移动到左方的子问题j -= 1# 由于回溯过程中字符是从 LCS 的末尾开始添加的,所以需要反转结果列表return "".join(res[::-1])print(lcs_traceback("ABCBDAB", "BDCABA"))  # BDAB

2 欧几里得算法

在这里插入图片描述
在这里插入图片描述

def gcd(a: int, b: int) -> int:"""递归求解两个数的最大公约数 (GCD)。使用欧几里得算法通过递归的方式计算两个整数的最大公约数。当第二个数 b 为 0 时,最大公约数是第一个数 a。:param a: 第一个整数:param b: 第二个整数:return: 返回 a 和 b 的最大公约数"""if b == 0:return a  # 基本情况:当 b 为 0 时,a 是最大公约数else:# 递归调用:计算 b 和 a % b 的最大公约数return gcd(b, a % b)print(gcd(12, 16))  # 4def gcd2(a: int, b: int) -> int:"""非递归求解两个数的最大公约数 (GCD)。使用欧几里得算法通过迭代的方式计算两个整数的最大公约数。通过不断更新 a 和 b 直到 b 为 0,此时 a 就是最大公约数。:param a: 第一个整数:param b: 第二个整数:return: 返回 a 和 b 的最大公约数"""while b > 0:r = a % b  # 计算 a 除以 b 的余数a = b  # 更新 a 为 bb = r  # 更新 b 为余数return a  # 当 b 为 0 时,a 是最大公约数print(gcd2(12, 16))  # 4

2.1 动态规划之欧几里得算法-分数

class Fraction:def __init__(self, a: int, b: int):"""初始化一个分数对象,并将其化简为最简分数。:param a: 分子:param b: 分母"""self.a = aself.b = b# 计算最大公约数x = self.gcd(a, b)# 将分子和分母除以最大公约数,化简为最简分数self.a /= xself.b /= x@staticmethoddef gcd(a: int, b: int) -> int:"""非递归求解两个数的最大公约数 (GCD)。使用欧几里得算法通过迭代的方式计算两个整数的最大公约数。通过不断更新 a 和 b 直到 b 为 0,此时 a 就是最大公约数。:param a: 第一个整数:param b: 第二个整数:return: 返回 a 和 b 的最大公约数"""while b > 0:r = a % b  # 计算 a 除以 b 的余数a = b  # 更新 a 为 bb = r  # 更新 b 为余数return a  # 当 b 为 0 时,a 是最大公约数def __str__(self) -> str:"""返回分数的字符串表示形式。:return: 返回分数的字符串表示,例如 "3/4""""return f"{int(self.a)}/{int(self.b)}"@staticmethoddef zgs(a: int, b: int) -> int:"""计算两个数的最小公倍数 (Least Common Multiple, LCM)。使用公式 LCM(a, b) = abs(a * b) / GCD(a, b) 来计算最小公倍数。:param a: 第一个整数:param b: 第二个整数:return: 返回 a 和 b 的最小公倍数,类型为整数"""x = Fraction.gcd(a, b)  # 调用静态方法 gcd 计算最大公约数return a * b // x  # 根据公式计算最小公倍数,使用整数除法返回整数结果def __add__(self, other: 'Fraction') -> 'Fraction':# 3/5 + 2/7"""重载加法运算符,实现两个分数相加。通过计算两个分数的最小公倍数来统一分母,并计算新分数的分子。:param self: 第一个分数对象:param other: 第二个分数对象:return: 返回两个分数相加后的结果,作为新的 Fraction 对象"""a = self.a  # 当前分数的分子b = self.b  # 当前分数的分母c = other.a  # 另一个分数的分子d = other.b  # 另一个分数的分母denominator = self.zgs(b, d)  # 计算两个分数分母的最小公倍数numerator = a * denominator // b + c * denominator // d  # 计算新分数的分子,使用整数除法确保结果为整数return Fraction(int(numerator), int(denominator))  # 返回新的 Fraction 对象,表示两个分数相加的结果# f = Fraction(30, 16)
# print(f)  # 输出 15/8a = Fraction(3, 4)
b = Fraction(1, 2)
print(a + b)  # 5/6

3 RSA算法-密码于加密

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这篇关于【算法进阶2-动态规划】最长公共子序列、欧几里得算法-分数、RSA算法-密码于加密的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107785

相关文章

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

MySQL8 密码强度评估与配置详解

《MySQL8密码强度评估与配置详解》MySQL8默认启用密码强度插件,实施MEDIUM策略(长度8、含数字/字母/特殊字符),支持动态调整与配置文件设置,推荐使用STRONG策略并定期更新密码以提... 目录一、mysql 8 密码强度评估机制1.核心插件:validate_password2.密码策略级

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支

MySQL设置密码复杂度策略的完整步骤(附代码示例)

《MySQL设置密码复杂度策略的完整步骤(附代码示例)》MySQL密码策略还可能包括密码复杂度的检查,如是否要求密码包含大写字母、小写字母、数字和特殊字符等,:本文主要介绍MySQL设置密码复杂度... 目录前言1. 使用 validate_password 插件1.1 启用 validate_passwo

基于Python编写自动化邮件发送程序(进阶版)

《基于Python编写自动化邮件发送程序(进阶版)》在数字化时代,自动化邮件发送功能已成为企业和个人提升工作效率的重要工具,本文将使用Python编写一个简单的自动化邮件发送程序,希望对大家有所帮助... 目录理解SMTP协议基础配置开发环境构建邮件发送函数核心逻辑实现完整发送流程添加附件支持功能实现htm

浅谈MySQL的容量规划

《浅谈MySQL的容量规划》进行MySQL的容量规划是确保数据库能够在当前和未来的负载下顺利运行的重要步骤,容量规划包括评估当前资源使用情况、预测未来增长、调整配置和硬件资源等,感兴趣的可以了解一下... 目录一、评估当前资源使用情况1.1 磁盘空间使用1.2 内存使用1.3 CPU使用1.4 网络带宽二、

Linux中的自定义协议+序列反序列化用法

《Linux中的自定义协议+序列反序列化用法》文章探讨网络程序在应用层的实现,涉及TCP协议的数据传输机制、结构化数据的序列化与反序列化方法,以及通过JSON和自定义协议构建网络计算器的思路,强调分层... 目录一,再次理解协议二,序列化和反序列化三,实现网络计算器3.1 日志文件3.2Socket.hpp