一道集众多技巧于一身的题目——《密文游戏》

本文详细解析了一道结合多种算法技巧的题目——《密文游戏》,涉及动态规划、状态转移、空间复杂度优化、大数运算优化等。通过分析和实现过程,介绍了如何运用动态规划解决方案统计问题,并逐步优化代码,降低空间复杂度和提高运算效率。

小伙伴们好,卷卷毛又来了,今天来分享一个非常具有技巧性的题目。

这是一道状态统计题目,同时兼具了若干技巧,有优化空间复杂度的数组减维,还有处理超大数据运算的高精度以及压位处理…也许这些技巧中有小伙伴们不熟悉的词汇,不过不要紧张,在下面对题目的分析中,我们会一一讨论到。
在这里插入图片描述

题面

那我们话不多说,先看题目:
在这里插入图片描述
时空限制:
在这里插入图片描述
输入样例:

1414
BE

输出样例:

3

分析与实现

题目大意是,给定两个字符串作为原文和密文。译码后,密文为原文的一个子序列(注意不是子串,不必在原文中连续出现)。问将密文还原为原文有多少种还原方式。

分析

简单分析题目,在将源码转成译码之后就是一道方案统计的问题。一般来说,方案统计的问题也需要借助状态之间的转移,所以我们也总是将这种方案统计的问题与动态规划问题统称为DP,尽管这类问题不涉及最优解。

所以,这个问题我们依旧可以使用之前用来解决动态规划问题的思想,在状态转移的过程中完成对结果方案的统计,即:定状态,找转移,初始化。

(顺便打个广告,之前动态规划相关的文章在这里:区间动态规划 例题与解析最短路径的方案数统计问题(基于floyd算法) 背包dp问题:背包九讲
在这里插入图片描述
好了,我们言归正传~

定状态

对于这个问题,我们可以定义状态:
d p [ i ] [ j ] ( j ≤ i , 0 ≤ i ≤ n , 0 ≤ j ≤ m ) n = l e n ( A ) m = l e n ( B ) dp[i][j](j \le i,0 \le i \le n,0 \le j \le m) \\ n = len(A) \\ m = len(B) dp[i][j](ji,0in,0jm)n=len(A)m=len(B)
表示 a 1 a 2 . . a i a_1a_2..a_i a1a2..ai b 1 b 2 . . b j b_1b_2..b_j b1b2..bj补全匹配的方案数

找转移

定义好了状态,来处理状态间的转移。

可以分成两种情况:

  • a i a_i ai b j b_j bj不相同时, d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i - 1][j] dp[i][j]=dp[i1][j],即最后一位不匹配,方案数同上一位 a i − 1 a_{i-1} ai1匹配到 b j b_j bj相同。
  • a i a_i ai b j b_j bj相同时, d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + d p [ i − 1 ] [ j ] dp[i][j]=dp[i - 1][j - 1] + dp[i - 1][j] dp[i][j]=dp[i1][j1]+dp[i1][j],即可以取最后一位不匹配,方案数同上;加上可以取最后一位匹配,方案数取上一位 a i − 1 a_{i-1} ai1 b j − 1 b_{j-1} bj1
### 简单唯密文题目举例与解析 #### 题目一:简单的替换密码 - **题目描述**:已知密文为 "XULY",该密文是通过简单的字母替换加密,即每个字母被替换为字母表中它后面第 3 个字母(例如,A 被替换为 D,B 被替换为 E 等)。尝试解密该密文。 - **解析**:对于简单的替换密码,解密的方法是将密文中的每个字母在字母表中向前移动相应的位数。在这个例子中,将每个字母向前移动 3 位。 ```python ciphertext = "XULY" plaintext = "" for char in ciphertext: # 计算解密后的字母的 ASCII 码 decrypted_char = chr((ord(char) - ord('A') - 3) % 26 + ord('A')) plaintext += decrypted_char print(plaintext) ``` 运行上述代码,得到明文为 "TQIH"。 #### 题目二:RSA 唯密文攻击(简化示例) - **题目描述**:已知 RSA 加密系统中,公钥 \(n = 33\),\(e = 3\),密文 \(C = 8\)。尝试解密该密文。 - **解析**:首先需要对 \(n\) 进行分解,找到 \(p\) 和 \(q\),使得 \(n = p \times q\)。在这个例子中,\(n = 33 = 3 \times 11\)。然后计算 \(\varphi(n)=(p - 1)(q - 1)=(3 - 1)\times(11 - 1)=20\)。接着求 \(e\) 关于 \(\varphi(n)\) 的模逆元 \(d\),即 \(e\times d\equiv 1\pmod{\varphi(n)}\),通过扩展欧几里得算法可求得 \(d = 7\)。最后,根据解密公式 \(M = C^d\bmod n\) 计算明文 \(M\)。 ```python n = 33 e = 3 C = 8 # 分解 n p = 3 q = 11 # 计算 φ(n) phi_n = (p - 1) * (q - 1) # 求 e 关于 φ(n) 的模逆元 d def mod_inverse(e, phi_n): for d in range(1, phi_n): if (e * d) % phi_n == 1: return d return None d = mod_inverse(e, phi_n) # 解密明文 M = pow(C, d, n) print(M) ``` 运行上述代码,得到明文 \(M = 17\)。 #### 题目三:压缩密文处理 - **题目描述**:华华接到任务,要对一个仅有英文字母的密文进行压缩处理,将其中连续的重复字母压缩成“一个字母 + 个数”的形式。例如:“AaaaaaaaAaaBbBaAC” 应压缩成 “A11B3A2C”。但是华华拿到的密码已经被别人处理过,密文没有完全压缩好,处理起来反而更麻烦。如上述密文可能已变成 “Aa10b2BaAC”。请编程帮华华完成任务。 - **解析**:可以通过遍历密文,统计连续相同字母的个数,然后将其压缩成所需的形式。 ```python def compress_ciphertext(ciphertext): result = "" i = 0 while i < len(ciphertext): if i + 1 < len(ciphertext) and ciphertext[i + 1].isdigit(): count_str = "" j = i + 1 while j < len(ciphertext) and ciphertext[j].isdigit(): count_str += ciphertext[j] j += 1 count = int(count_str) result += ciphertext[i].upper() + str(count) i = j else: count = 1 j = i + 1 while j < len(ciphertext) and ciphertext[j].lower() == ciphertext[i].lower(): count += 1 j += 1 result += ciphertext[i].upper() + str(count) i = j return result ciphertext = "Aa10b2BaAC" print(compress_ciphertext(ciphertext)) ``` 运行上述代码,得到压缩后的密文为 “A11B3A2C”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值