【算法进阶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

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring