2227-加密解密字符串
给你一个字符数组 keys
,由若干 互不相同 的字符组成。还有一个字符串数组 values
,内含若干长度为 2
的字符串。另给你一个字符串数组 dictionary
,包含解密后所有允许的原字符串。请你设计并实现一个支持加密及解密下标从 0
开始字符串的数据结构。
字符串 加密 按下述步骤进行:
- 对字符串中的每个字符
c
,先从keys
中找出满足keys[i] == c
的下标i
。 - 在字符串中,用
values[i]
替换字符c
。
字符串 解密 按下述步骤进行:
- 将字符串每相邻 2 个字符划分为一个子字符串,对于每个子字符串
s
,找出满足values[i] == s
的一个下标i
。如果存在多个有效的i
,从中选择 任意 一个。这意味着一个字符串解密可能得到多个解密字符串。 - 在字符串中,用
keys[i]
替换s
。
实现 Encrypter
类:
Encrypter(char[] keys, String[] values, String[] dictionary)
用keys
、values
和dictionary
初始化Encrypter
类。String encrypt(String word1)
按上述加密过程完成对word1
的加密,并返回加密后的字符串。int decrypt(String word2)
统计并返回可以由word2
解密得到且出现在dictionary
中的字符串数目。
示例:
**输入:**
["Encrypter", "encrypt", "decrypt"]
[[['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]], ["abcd"], ["eizfeiam"]]
**输出:**
[null, "eizfeiam", 2]
**解释:**
Encrypter encrypter = new Encrypter([['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]);
encrypter.encrypt("abcd"); // 返回 "eizfeiam"。
// 'a' 映射为 "ei",'b' 映射为 "zf",'c' 映射为 "ei",'d' 映射为 "am"。
encrypter.decrypt("eizfeiam"); // return 2.
// "ei" 可以映射为 'a' 或 'c',"zf" 映射为 'b',"am" 映射为 'd'。
// 因此,解密后可以得到的字符串是 "abad","cbad","abcd" 和 "cbcd"。
// 其中 2 个字符串,"abad" 和 "abcd",在 dictionary 中出现,所以答案是 2 。
提示:
1 <= keys.length == values.length <= 26
values[i].length == 2
1 <= dictionary.length <= 100
1 <= dictionary[i].length <= 100
- 所有
keys[i]
和dictionary[i]
互不相同 1 <= word1.length <= 2000
1 <= word2.length <= 200
- 所有
word1[i]
都出现在keys
中 word2.length
是偶数keys
、values[i]
、dictionary[i]
、word1
和word2
只含小写英文字母- 至多调用
encrypt
和decrypt
总计200
次
方法一:直接加密 + 预处理解密
思路与算法
我们首先可以使用 enc 哈希映射存储单个字母的加密关系,即对于 enc 中的每个键值对,键表示单个字母,值表示该字母加密得到的长度为 2 的字符串。这样一来,对于 encrypt(word) 操作,我们只需要遍历字符串 word,对每个字母分别根据哈希映射进行加密,再合并结果得到最终的字符串即可。
而对于 decrypt(word) 操作,如果我们直接按照题目中的要求进行分组、解密、判断是否在字典中,那么必然会使用深度优先搜索或者更高级的数据结构(例如字典树)。一种更简单的方法是「逆向思考」:我们直接把字典中的所有单词进行加密,如果该单词可以被加密,那么我们就将加密的结果存储在另一个哈希映射 dec_count 中,键表示加密的结果,值表示该结果出现的次数(因为多个单词可以被加密成相同的结果)。这样一来,我们只需要返回 word 作为键在哈希映射中对应的值即可。
代码
1 | class Encrypter { |
1 | class Encrypter: |
复杂度分析
时间复杂度:
初始化的时间复杂度为 O(k + d \times l_d),其中 k 分别是数组 keys 和 values 的长度,d 是数组 dictionary 的长度,l_d 是数组 dictionary 中单词的平均长度;
encrypt(word) 的时间复杂度为 O(|\textit{word}|);
decrypt(word) 的时间复杂度为 O(|\textit{word}|)。
空间复杂度:O(k + d \times l_d),即为两个哈希映射需要使用的空间。