📅  最后修改于: 2023-12-03 15:28:48.898000             🧑  作者: Mango
此题出自地球科学与技术学院门|门CS 2010:
小明正在研究一种远古的密码系统,他得到了以下加密方式的信息:
例如,原文为“CRYPTOGRAPHY”,矩阵的规格为 3 × 4,则加密后的密文为“CYAPORRGTYPH”。
小明已经成功地解密出了一些密文,但他发现这种密码系统的矩阵规格是由发信人任意指定的,并且一个密文可能有很多种矩阵规格,并且里面可能含有很多无用的字符。你能帮助他吗?
实现一个函数 decode(str: str) -> str
,用来解密字符串 str 并返回解密后的字符串。其中,str 是一个非空字符串,由大小写字母和其它 ASCII 码组成,其长度不超过 20000。
请您实现 decode
函数。详细说明请参见下面的函数说明。
def decode(str: str) -> str:
pass
解密后的原文(仅包含大小写字母)
>>> decode("PTIRGFRRYYYPHCOOEEQLZUJCBTEUJZUFCFFCRWYMNNZGLXHSEHZIBVLGQAEBLCKWJRIELBHLNWWNSVVZMBIEGBKDFXWDRZSRLSOKMI")
'CRYPOTGRAPHY'
>>> decode("RTGOICGQPYRYCRXHPTCIHQAOHYOKCZQRUPGATL");
'CRYPTOGRAPHY'
上面所有的函数返回值和输入参数类型请按照题目要求严格执行。
题目要求我们解密一个加密字符串,这个加密字符串包含了很多无用字符,我们需要把这个字符串恢复成原来的字符串。具体的解密方式如题目描述,这里不再赘述。
首先,我们需要找到这个加密字符串所能对应的所有矩阵规格。
假设这个加密字符串中有 n 个合法的字符,可以分为 m 行 k 列进行排列。则由于整个字符串长度为 len,则有:
mk = n
mk <= len
我们可以通过循环,枚举每一个 mk,判断 len 是否为 mk 的整数倍,来获得 m 和 k 的取值:
for i in range(1, len+1):
if len % i == 0:
m, k = i, len // i
然后我们再依次从 str 中选取前 mk 个有效字符,组成一个 m 行 k 列的二维矩阵 matrix,并按照题目要求,按列从上到下转换为原文字符:
matrix = [[0] * k for i in range(m)]
for i in range(m):
for j in range(k):
matrix[i][j] = str[i*k+j]
s = ''
for j in range(k):
for i in range(m):
s += matrix[i][j]
得到 s 后,我们就可以进行比较了,判断其是否为原来的文本。注意,原文的字符是按照字母表的升序排列后转换而来的,所以也需要暴力枚举并比较排序后的文本。
最后,将所有能够成功解密的原文进行比较,输出字母表顺序最早的一项即可。
def decode(str):
l = len(str)
for i in range(1, l+1):
if l % i == 0:
m, k = i, l // i
matrix = [[0] * k for i in range(m)]
for i in range(m):
for j in range(k):
matrix[i][j] = str[i*k+j]
s = ''
for j in range(k):
for i in range(m):
s += matrix[i][j]
sort_s = sorted(s)
sort_str = sorted(str)
if sort_s == sort_str:
return ''.join(sorted(set(s), key=s.index))