Description
You are given a character array keys containing unique characters and a string array values containing strings of length 2. You are also given another string array dictionary that contains all permitted original strings after decryption. You should implement a data structure that can encrypt or decrypt a 0-indexed string.
A string is encrypted with the following process:
- For each character
cin the string, we find the indexisatisfyingkeys[i] == cinkeys. - Replace
cwithvalues[i]in the string.
Note that in case a character of the string is not present in keys, the encryption process cannot be carried out, and an empty string "" is returned.
A string is decrypted with the following process:
- For each substring
sof length 2 occurring at an even index in the string, we find anisuch thatvalues[i] == s. If there are multiple validi, we choose any one of them. This means a string could have multiple possible strings it can decrypt to. - Replace
swithkeys[i]in the string.
Implement the Encrypter class:
Encrypter(char[] keys, String[] values, String[] dictionary)Initializes theEncrypterclass withkeys, values, anddictionary.String encrypt(String word1)Encryptsword1with the encryption process described above and returns the encrypted string.int decrypt(String word2)Returns the number of possible stringsword2could decrypt to that also appear indictionary.
Example 1:
Input
["Encrypter", "encrypt", "decrypt"]
[[['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]], ["abcd"], ["eizfeiam"]]
Output
[null, "eizfeiam", 2]
Explanation
Encrypter encrypter = new Encrypter([['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]);
encrypter.encrypt("abcd"); // return "eizfeiam".
// 'a' maps to "ei", 'b' maps to "zf", 'c' maps to "ei", and 'd' maps to "am".
encrypter.decrypt("eizfeiam"); // return 2.
// "ei" can map to 'a' or 'c', "zf" maps to 'b', and "am" maps to 'd'.
// Thus, the possible strings after decryption are "abad", "cbad", "abcd", and "cbcd".
// 2 of those strings, "abad" and "abcd", appear in dictionary, so the answer is 2.
Constraints:
1 <= keys.length == values.length <= 26values[i].length == 21 <= dictionary.length <= 1001 <= dictionary[i].length <= 100- All
keys[i]anddictionary[i]are unique. 1 <= word1.length <= 20002 <= word2.length <= 200- All
word1[i]appear inkeys. word2.lengthis even.keys,values[i],dictionary[i],word1, andword2only contain lowercase English letters.- At most
200calls will be made toencryptanddecryptin total.
Solutions
Solution 1: Hash Table
We use a hash table mp to record the encryption result of each character, and another hash table cnt to record the number of occurrences of each encryption result.
In the constructor, we traverse keys and values, storing each character and its corresponding encryption result in mp. Then, we traverse dictionary to count the occurrences of each encryption result. The time complexity is O(n + m), where n and m are the lengths of keys and dictionary, respectively.
In the encryption function, we traverse each character of the input string word1, look up its encryption result, and concatenate them. If a character does not have a corresponding encryption result, it means encryption is not possible, and we return an empty string. The time complexity is O(k), where k is the length of word1.
In the decryption function, we directly return the count of word2 in cnt. The time complexity is O(1).
The space complexity is O(n + m).
class Encrypter: def __init__(self, keys: List[str], values: List[str], dictionary: List[str]): self.mp = dict(zip(keys, values)) self.cnt = Counter(self.encrypt(v) for v in dictionary) def encrypt(self, word1: str) -> str: res = [] for c in word1: if c not in self.mp: return '' res.append(self.mp[c]) return ''.join(res) def decrypt(self, word2: str) -> int: return self.cnt[word2] # Your Encrypter object will be instantiated and called as such: # obj = Encrypter(keys, values, dictionary) # param_1 = obj.encrypt(word1) # param_2 = obj.decrypt(word2)(code-box)
