{ "data": { "question": { "questionId": "1433", "questionFrontendId": "2227", "boundTopicId": null, "title": "Encrypt and Decrypt Strings", "titleSlug": "encrypt-and-decrypt-strings", "content": "

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.

\n\n

A string is encrypted with the following process:

\n\n
    \n\t
  1. For each character c in the string, we find the index i satisfying keys[i] == c in keys.
  2. \n\t
  3. Replace c with values[i] in the string.
  4. \n
\n\n

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.

\n\n

A string is decrypted with the following process:

\n\n
    \n\t
  1. For each substring s of length 2 occurring at an even index in the string, we find an i such that values[i] == s. If there are multiple valid i, we choose any one of them. This means a string could have multiple possible strings it can decrypt to.
  2. \n\t
  3. Replace s with keys[i] in the string.
  4. \n
\n\n

Implement the Encrypter class:

\n\n\n\n

 

\n

Example 1:

\n\n
\nInput\n["Encrypter", "encrypt", "decrypt"]\n[[['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]], ["abcd"], ["eizfeiam"]]\nOutput\n[null, "eizfeiam", 2]\n\nExplanation\nEncrypter encrypter = new Encrypter([['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]);\nencrypter.encrypt("abcd"); // return "eizfeiam". \n                           // 'a' maps to "ei", 'b' maps to "zf", 'c' maps to "ei", and 'd' maps to "am".\nencrypter.decrypt("eizfeiam"); // return 2. \n                              // "ei" can map to 'a' or 'c', "zf" maps to 'b', and "am" maps to 'd'. \n                              // Thus, the possible strings after decryption are "abad", "cbad", "abcd", and "cbcd". \n                              // 2 of those strings, "abad" and "abcd", appear in dictionary, so the answer is 2.\n
\n\n

 

\n

Constraints:

\n\n\n", "translatedTitle": null, "translatedContent": null, "isPaidOnly": false, "difficulty": "Hard", "likes": 186, "dislikes": 35, "isLiked": null, "similarQuestions": "[{\"title\": \"Implement Trie (Prefix Tree)\", \"titleSlug\": \"implement-trie-prefix-tree\", \"difficulty\": \"Medium\", \"translatedTitle\": null}, {\"title\": \"Word Search II\", \"titleSlug\": \"word-search-ii\", \"difficulty\": \"Hard\", \"translatedTitle\": null}, {\"title\": \"Implement Trie II (Prefix Tree)\", \"titleSlug\": \"implement-trie-ii-prefix-tree\", \"difficulty\": \"Medium\", \"translatedTitle\": null}]", "exampleTestcases": "[\"Encrypter\",\"encrypt\",\"decrypt\"]\n[[[\"a\",\"b\",\"c\",\"d\"],[\"ei\",\"zf\",\"ei\",\"am\"],[\"abcd\",\"acbd\",\"adbc\",\"badc\",\"dacb\",\"cadb\",\"cbda\",\"abad\"]],[\"abcd\"],[\"eizfeiam\"]]", "categoryTitle": "Algorithms", "contributors": [], "topicTags": [ { "name": "Array", "slug": "array", "translatedName": null, "__typename": "TopicTagNode" }, { "name": "Hash Table", "slug": "hash-table", "translatedName": null, "__typename": "TopicTagNode" }, { "name": "String", "slug": "string", "translatedName": null, "__typename": "TopicTagNode" }, { "name": "Design", "slug": "design", "translatedName": null, "__typename": "TopicTagNode" }, { "name": "Trie", "slug": "trie", "translatedName": null, "__typename": "TopicTagNode" } ], "companyTagStats": null, "codeSnippets": [ { "lang": "C++", "langSlug": "cpp", "code": "class Encrypter {\npublic:\n Encrypter(vector& keys, vector& values, vector& dictionary) {\n \n }\n \n string encrypt(string word1) {\n \n }\n \n int decrypt(string word2) {\n \n }\n};\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * Encrypter* obj = new Encrypter(keys, values, dictionary);\n * string param_1 = obj->encrypt(word1);\n * int param_2 = obj->decrypt(word2);\n */", "__typename": "CodeSnippetNode" }, { "lang": "Java", "langSlug": "java", "code": "class Encrypter {\n\n public Encrypter(char[] keys, String[] values, String[] dictionary) {\n \n }\n \n public String encrypt(String word1) {\n \n }\n \n public int decrypt(String word2) {\n \n }\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * Encrypter obj = new Encrypter(keys, values, dictionary);\n * String param_1 = obj.encrypt(word1);\n * int param_2 = obj.decrypt(word2);\n */", "__typename": "CodeSnippetNode" }, { "lang": "Python", "langSlug": "python", "code": "class Encrypter(object):\n\n def __init__(self, keys, values, dictionary):\n \"\"\"\n :type keys: List[str]\n :type values: List[str]\n :type dictionary: List[str]\n \"\"\"\n \n\n def encrypt(self, word1):\n \"\"\"\n :type word1: str\n :rtype: str\n \"\"\"\n \n\n def decrypt(self, word2):\n \"\"\"\n :type word2: str\n :rtype: int\n \"\"\"\n \n\n\n# Your Encrypter object will be instantiated and called as such:\n# obj = Encrypter(keys, values, dictionary)\n# param_1 = obj.encrypt(word1)\n# param_2 = obj.decrypt(word2)", "__typename": "CodeSnippetNode" }, { "lang": "Python3", "langSlug": "python3", "code": "class Encrypter:\n\n def __init__(self, keys: List[str], values: List[str], dictionary: List[str]):\n \n\n def encrypt(self, word1: str) -> str:\n \n\n def decrypt(self, word2: str) -> int:\n \n\n\n# Your Encrypter object will be instantiated and called as such:\n# obj = Encrypter(keys, values, dictionary)\n# param_1 = obj.encrypt(word1)\n# param_2 = obj.decrypt(word2)", "__typename": "CodeSnippetNode" }, { "lang": "C", "langSlug": "c", "code": "\n\n\ntypedef struct {\n \n} Encrypter;\n\n\nEncrypter* encrypterCreate(char* keys, int keysSize, char ** values, int valuesSize, char ** dictionary, int dictionarySize) {\n \n}\n\nchar * encrypterEncrypt(Encrypter* obj, char * word1) {\n \n}\n\nint encrypterDecrypt(Encrypter* obj, char * word2) {\n \n}\n\nvoid encrypterFree(Encrypter* obj) {\n \n}\n\n/**\n * Your Encrypter struct will be instantiated and called as such:\n * Encrypter* obj = encrypterCreate(keys, keysSize, values, valuesSize, dictionary, dictionarySize);\n * char * param_1 = encrypterEncrypt(obj, word1);\n \n * int param_2 = encrypterDecrypt(obj, word2);\n \n * encrypterFree(obj);\n*/", "__typename": "CodeSnippetNode" }, { "lang": "C#", "langSlug": "csharp", "code": "public class Encrypter {\n\n public Encrypter(char[] keys, string[] values, string[] dictionary) {\n \n }\n \n public string Encrypt(string word1) {\n \n }\n \n public int Decrypt(string word2) {\n \n }\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * Encrypter obj = new Encrypter(keys, values, dictionary);\n * string param_1 = obj.Encrypt(word1);\n * int param_2 = obj.Decrypt(word2);\n */", "__typename": "CodeSnippetNode" }, { "lang": "JavaScript", "langSlug": "javascript", "code": "/**\n * @param {character[]} keys\n * @param {string[]} values\n * @param {string[]} dictionary\n */\nvar Encrypter = function(keys, values, dictionary) {\n \n};\n\n/** \n * @param {string} word1\n * @return {string}\n */\nEncrypter.prototype.encrypt = function(word1) {\n \n};\n\n/** \n * @param {string} word2\n * @return {number}\n */\nEncrypter.prototype.decrypt = function(word2) {\n \n};\n\n/** \n * Your Encrypter object will be instantiated and called as such:\n * var obj = new Encrypter(keys, values, dictionary)\n * var param_1 = obj.encrypt(word1)\n * var param_2 = obj.decrypt(word2)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Ruby", "langSlug": "ruby", "code": "class Encrypter\n\n=begin\n :type keys: Character[]\n :type values: String[]\n :type dictionary: String[]\n=end\n def initialize(keys, values, dictionary)\n \n end\n\n\n=begin\n :type word1: String\n :rtype: String\n=end\n def encrypt(word1)\n \n end\n\n\n=begin\n :type word2: String\n :rtype: Integer\n=end\n def decrypt(word2)\n \n end\n\n\nend\n\n# Your Encrypter object will be instantiated and called as such:\n# obj = Encrypter.new(keys, values, dictionary)\n# param_1 = obj.encrypt(word1)\n# param_2 = obj.decrypt(word2)", "__typename": "CodeSnippetNode" }, { "lang": "Swift", "langSlug": "swift", "code": "\nclass Encrypter {\n\n init(_ keys: [Character], _ values: [String], _ dictionary: [String]) {\n \n }\n \n func encrypt(_ word1: String) -> String {\n \n }\n \n func decrypt(_ word2: String) -> Int {\n \n }\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * let obj = Encrypter(keys, values, dictionary)\n * let ret_1: String = obj.encrypt(word1)\n * let ret_2: Int = obj.decrypt(word2)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Go", "langSlug": "golang", "code": "type Encrypter struct {\n \n}\n\n\nfunc Constructor(keys []byte, values []string, dictionary []string) Encrypter {\n \n}\n\n\nfunc (this *Encrypter) Encrypt(word1 string) string {\n \n}\n\n\nfunc (this *Encrypter) Decrypt(word2 string) int {\n \n}\n\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * obj := Constructor(keys, values, dictionary);\n * param_1 := obj.Encrypt(word1);\n * param_2 := obj.Decrypt(word2);\n */", "__typename": "CodeSnippetNode" }, { "lang": "Scala", "langSlug": "scala", "code": "class Encrypter(_keys: Array[Char], _values: Array[String], _dictionary: Array[String]) {\n\n def encrypt(word1: String): String = {\n \n }\n\n def decrypt(word2: String): Int = {\n \n }\n\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * var obj = new Encrypter(keys, values, dictionary)\n * var param_1 = obj.encrypt(word1)\n * var param_2 = obj.decrypt(word2)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Kotlin", "langSlug": "kotlin", "code": "class Encrypter(keys: CharArray, values: Array, dictionary: Array) {\n\n fun encrypt(word1: String): String {\n \n }\n\n fun decrypt(word2: String): Int {\n \n }\n\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * var obj = Encrypter(keys, values, dictionary)\n * var param_1 = obj.encrypt(word1)\n * var param_2 = obj.decrypt(word2)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Rust", "langSlug": "rust", "code": "struct Encrypter {\n\n}\n\n\n/** \n * `&self` means the method takes an immutable reference.\n * If you need a mutable reference, change it to `&mut self` instead.\n */\nimpl Encrypter {\n\n fn new(keys: Vec, values: Vec, dictionary: Vec) -> Self {\n \n }\n \n fn encrypt(&self, word1: String) -> String {\n \n }\n \n fn decrypt(&self, word2: String) -> i32 {\n \n }\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * let obj = Encrypter::new(keys, values, dictionary);\n * let ret_1: String = obj.encrypt(word1);\n * let ret_2: i32 = obj.decrypt(word2);\n */", "__typename": "CodeSnippetNode" }, { "lang": "PHP", "langSlug": "php", "code": "class Encrypter {\n /**\n * @param String[] $keys\n * @param String[] $values\n * @param String[] $dictionary\n */\n function __construct($keys, $values, $dictionary) {\n \n }\n \n /**\n * @param String $word1\n * @return String\n */\n function encrypt($word1) {\n \n }\n \n /**\n * @param String $word2\n * @return Integer\n */\n function decrypt($word2) {\n \n }\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * $obj = Encrypter($keys, $values, $dictionary);\n * $ret_1 = $obj->encrypt($word1);\n * $ret_2 = $obj->decrypt($word2);\n */", "__typename": "CodeSnippetNode" }, { "lang": "TypeScript", "langSlug": "typescript", "code": "class Encrypter {\n constructor(keys: string[], values: string[], dictionary: string[]) {\n\n }\n\n encrypt(word1: string): string {\n\n }\n\n decrypt(word2: string): number {\n\n }\n}\n\n/**\n * Your Encrypter object will be instantiated and called as such:\n * var obj = new Encrypter(keys, values, dictionary)\n * var param_1 = obj.encrypt(word1)\n * var param_2 = obj.decrypt(word2)\n */", "__typename": "CodeSnippetNode" }, { "lang": "Racket", "langSlug": "racket", "code": "(define encrypter%\n (class object%\n (super-new)\n \n ; keys : (listof char?)\n ; values : (listof string?)\n ; dictionary : (listof string?)\n (init-field\n keys\n values\n dictionary)\n \n ; encrypt : string? -> string?\n (define/public (encrypt word1)\n\n )\n ; decrypt : string? -> exact-integer?\n (define/public (decrypt word2)\n\n )))\n\n;; Your encrypter% object will be instantiated and called as such:\n;; (define obj (new encrypter% [keys keys] [values values] [dictionary dictionary]))\n;; (define param_1 (send obj encrypt word1))\n;; (define param_2 (send obj decrypt word2))", "__typename": "CodeSnippetNode" }, { "lang": "Erlang", "langSlug": "erlang", "code": "-spec encrypter_init_(Keys :: [char()], Values :: [unicode:unicode_binary()], Dictionary :: [unicode:unicode_binary()]) -> any().\nencrypter_init_(Keys, Values, Dictionary) ->\n .\n\n-spec encrypter_encrypt(Word1 :: unicode:unicode_binary()) -> unicode:unicode_binary().\nencrypter_encrypt(Word1) ->\n .\n\n-spec encrypter_decrypt(Word2 :: unicode:unicode_binary()) -> integer().\nencrypter_decrypt(Word2) ->\n .\n\n\n%% Your functions will be called as such:\n%% encrypter_init_(Keys, Values, Dictionary),\n%% Param_1 = encrypter_encrypt(Word1),\n%% Param_2 = encrypter_decrypt(Word2),\n\n%% encrypter_init_ will be called before every test case, in which you can do some necessary initializations.", "__typename": "CodeSnippetNode" }, { "lang": "Elixir", "langSlug": "elixir", "code": "defmodule Encrypter do\n @spec init_(keys :: [char], values :: [String.t], dictionary :: [String.t]) :: any\n def init_(keys, values, dictionary) do\n\n end\n\n @spec encrypt(word1 :: String.t) :: String.t\n def encrypt(word1) do\n\n end\n\n @spec decrypt(word2 :: String.t) :: integer\n def decrypt(word2) do\n\n end\nend\n\n# Your functions will be called as such:\n# Encrypter.init_(keys, values, dictionary)\n# param_1 = Encrypter.encrypt(word1)\n# param_2 = Encrypter.decrypt(word2)\n\n# Encrypter.init_ will be called before every test case, in which you can do some necessary initializations.", "__typename": "CodeSnippetNode" } ], "stats": "{\"totalAccepted\": \"7K\", \"totalSubmission\": \"18.4K\", \"totalAcceptedRaw\": 7017, \"totalSubmissionRaw\": 18443, \"acRate\": \"38.0%\"}", "hints": [ "For encryption, use hashmap to map each char of word1 to its value.", "For decryption, use trie to prune when necessary." ], "solution": null, "status": null, "sampleTestCase": "[\"Encrypter\",\"encrypt\",\"decrypt\"]\n[[[\"a\",\"b\",\"c\",\"d\"],[\"ei\",\"zf\",\"ei\",\"am\"],[\"abcd\",\"acbd\",\"adbc\",\"badc\",\"dacb\",\"cadb\",\"cbda\",\"abad\"]],[\"abcd\"],[\"eizfeiam\"]]", "metaData": "{\n \"classname\": \"Encrypter\",\n \"constructor\": {\n \"params\": [\n {\n \"name\": \"keys\",\n \"type\": \"character[]\"\n },\n {\n \"type\": \"string[]\",\n \"name\": \"values\"\n },\n {\n \"name\": \"dictionary\",\n \"type\": \"string[]\"\n }\n ]\n },\n \"methods\": [\n {\n \"params\": [\n {\n \"type\": \"string\",\n \"name\": \"word1\"\n }\n ],\n \"name\": \"encrypt\",\n \"return\": {\n \"type\": \"string\"\n }\n },\n {\n \"params\": [\n {\n \"type\": \"string\",\n \"name\": \"word2\"\n }\n ],\n \"name\": \"decrypt\",\n \"return\": {\n \"type\": \"integer\"\n }\n }\n ],\n \"return\": {\n \"type\": \"boolean\"\n },\n \"systemdesign\": true,\n \"manual\": false\n}", "judgerAvailable": true, "judgeType": "large", "mysqlSchemas": [], "enableRunCode": true, "enableTestMode": false, "enableDebugger": true, "envInfo": "{\"cpp\": [\"C++\", \"

Compiled with clang 11 using the latest C++ 17 standard.

\\r\\n\\r\\n

Your code is compiled with level two optimization (-O2). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.

\\r\\n\\r\\n

Most standard library headers are already included automatically for your convenience.

\"], \"java\": [\"Java\", \"

OpenJDK 17 . Java 8 features such as lambda expressions and stream API can be used.

\\r\\n\\r\\n

Most standard library headers are already included automatically for your convenience.

\\r\\n

Includes Pair class from https://docs.oracle.com/javase/8/javafx/api/javafx/util/Pair.html.

\"], \"python\": [\"Python\", \"

Python 2.7.12.

\\r\\n\\r\\n

Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.

\\r\\n\\r\\n

For Map/TreeMap data structure, you may use sortedcontainers library.

\\r\\n\\r\\n

Note that Python 2.7 will not be maintained past 2020. For the latest Python, please choose Python3 instead.

\"], \"c\": [\"C\", \"

Compiled with gcc 8.2 using the gnu99 standard.

\\r\\n\\r\\n

Your code is compiled with level one optimization (-O1). AddressSanitizer is also enabled to help detect out-of-bounds and use-after-free bugs.

\\r\\n\\r\\n

Most standard library headers are already included automatically for your convenience.

\\r\\n\\r\\n

For hash table operations, you may use uthash. \\\"uthash.h\\\" is included by default. Below are some examples:

\\r\\n\\r\\n

1. Adding an item to a hash.\\r\\n

\\r\\nstruct hash_entry {\\r\\n    int id;            /* we'll use this field as the key */\\r\\n    char name[10];\\r\\n    UT_hash_handle hh; /* makes this structure hashable */\\r\\n};\\r\\n\\r\\nstruct hash_entry *users = NULL;\\r\\n\\r\\nvoid add_user(struct hash_entry *s) {\\r\\n    HASH_ADD_INT(users, id, s);\\r\\n}\\r\\n
\\r\\n

\\r\\n\\r\\n

2. Looking up an item in a hash:\\r\\n

\\r\\nstruct hash_entry *find_user(int user_id) {\\r\\n    struct hash_entry *s;\\r\\n    HASH_FIND_INT(users, &user_id, s);\\r\\n    return s;\\r\\n}\\r\\n
\\r\\n

\\r\\n\\r\\n

3. Deleting an item in a hash:\\r\\n

\\r\\nvoid delete_user(struct hash_entry *user) {\\r\\n    HASH_DEL(users, user);  \\r\\n}\\r\\n
\\r\\n

\"], \"csharp\": [\"C#\", \"

C# 10 with .NET 6 runtime

\\r\\n\\r\\n

Your code is compiled with debug flag enabled (/debug).

\"], \"javascript\": [\"JavaScript\", \"

Node.js 16.13.2.

\\r\\n\\r\\n

Your code is run with --harmony flag, enabling new ES6 features.

\\r\\n\\r\\n

lodash.js library is included by default.

\\r\\n\\r\\n

For Priority Queue / Queue data structures, you may use datastructures-js/priority-queue and datastructures-js/queue.

\"], \"ruby\": [\"Ruby\", \"

Ruby 3.1

\\r\\n\\r\\n

Some common data structure implementations are provided in the Algorithms module: https://www.rubydoc.info/github/kanwei/algorithms/Algorithms

\"], \"swift\": [\"Swift\", \"

Swift 5.5.2.

\"], \"golang\": [\"Go\", \"

Go 1.17.6.

\\r\\n\\r\\n

Support https://godoc.org/github.com/emirpasic/gods library.

\"], \"python3\": [\"Python3\", \"

Python 3.10.

\\r\\n\\r\\n

Most libraries are already imported automatically for your convenience, such as array, bisect, collections. If you need more libraries, you can import it yourself.

\\r\\n\\r\\n

For Map/TreeMap data structure, you may use sortedcontainers library.

\"], \"scala\": [\"Scala\", \"

Scala 2.13.7.

\"], \"kotlin\": [\"Kotlin\", \"

Kotlin 1.3.10.

\"], \"rust\": [\"Rust\", \"

Rust 1.58.1

\\r\\n\\r\\n

Supports rand v0.6\\u00a0from crates.io

\"], \"php\": [\"PHP\", \"

PHP 8.1.

\\r\\n

With bcmath module

\"], \"typescript\": [\"Typescript\", \"

TypeScript 4.5.4, Node.js 16.13.2.

\\r\\n\\r\\n

Your code is run with --harmony flag, enabling new ES2020 features.

\\r\\n\\r\\n

lodash.js library is included by default.

\"], \"racket\": [\"Racket\", \"

Run with Racket 8.3.

\"], \"erlang\": [\"Erlang\", \"Erlang/OTP 24.2\"], \"elixir\": [\"Elixir\", \"Elixir 1.13.0 with Erlang/OTP 24.2\"]}", "libraryUrl": null, "adminUrl": null, "challengeQuestion": null, "__typename": "QuestionNode" } } }