{"id":9626,"date":"2022-04-03T02:39:44","date_gmt":"2022-04-03T09:39:44","guid":{"rendered":"https:\/\/zxi.mytechroad.com\/blog\/?p=9626"},"modified":"2022-04-03T19:22:26","modified_gmt":"2022-04-04T02:22:26","slug":"leetcode-2227-encrypt-and-decrypt-strings","status":"publish","type":"post","link":"https:\/\/zxi.mytechroad.com\/blog\/data-structure\/leetcode-2227-encrypt-and-decrypt-strings\/","title":{"rendered":"\u82b1\u82b1\u9171 LeetCode 2227. Encrypt and Decrypt Strings"},"content":{"rendered":"\n<p>You are given a character array&nbsp;<code>keys<\/code>&nbsp;containing&nbsp;<strong>unique<\/strong>&nbsp;characters and a string array&nbsp;<code>values<\/code>&nbsp;containing strings of length 2. You are also given another string array&nbsp;<code>dictionary<\/code>&nbsp;that contains all permitted original strings after decryption. You should implement a data structure that can encrypt or decrypt a&nbsp;<strong>0-indexed<\/strong>&nbsp;string.<\/p>\n\n\n\n<p>A string is&nbsp;<strong>encrypted<\/strong>&nbsp;with the following process:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>For each character&nbsp;<code>c<\/code>&nbsp;in the string, we find the index&nbsp;<code>i<\/code>&nbsp;satisfying&nbsp;<code>keys[i] == c<\/code>&nbsp;in&nbsp;<code>keys<\/code>.<\/li><li>Replace&nbsp;<code>c<\/code>&nbsp;with&nbsp;<code>values[i]<\/code>&nbsp;in the string.<\/li><\/ol>\n\n\n\n<p>A string is&nbsp;<strong>decrypted<\/strong>&nbsp;with the following process:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>For each substring&nbsp;<code>s<\/code>&nbsp;of length 2 occurring at an even index in the string, we find an&nbsp;<code>i<\/code>&nbsp;such that&nbsp;<code>values[i] == s<\/code>. If there are multiple valid&nbsp;<code>i<\/code>, we choose&nbsp;<strong>any<\/strong>&nbsp;one of them. This means a string could have multiple possible strings it can decrypt to.<\/li><li>Replace&nbsp;<code>s<\/code>&nbsp;with&nbsp;<code>keys[i]<\/code>&nbsp;in the string.<\/li><\/ol>\n\n\n\n<p>Implement the&nbsp;<code>Encrypter<\/code>&nbsp;class:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>Encrypter(char[] keys, String[] values, String[] dictionary)<\/code>&nbsp;Initializes the&nbsp;<code>Encrypter<\/code>&nbsp;class with&nbsp;<code>keys, values<\/code>, and&nbsp;<code>dictionary<\/code>.<\/li><li><code>String encrypt(String word1)<\/code>&nbsp;Encrypts&nbsp;<code>word1<\/code>&nbsp;with the encryption process described above and returns the encrypted string.<\/li><li><code>int decrypt(String word2)<\/code>&nbsp;Returns the number of possible strings&nbsp;<code>word2<\/code>&nbsp;could decrypt to that also appear in&nbsp;<code>dictionary<\/code>.<\/li><\/ul>\n\n\n\n<p><strong>Example 1:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input<\/strong>\n[\"Encrypter\", \"encrypt\", \"decrypt\"]\n[[['a', 'b', 'c', 'd'], [\"ei\", \"zf\", \"ei\", \"am\"], [\"abcd\", \"acbd\", \"adbc\", \"badc\", \"dacb\", \"cadb\", \"cbda\", \"abad\"]], [\"abcd\"], [\"eizfeiam\"]]\n<strong>Output<\/strong>\n<\/pre>\n\n\n<p>[null, &#8220;eizfeiam&#8221;, 2]<\/p>\n\n\n\n<p><strong>Explanation<\/strong> Encrypter encrypter = new Encrypter([[&#8216;a&#8217;, &#8216;b&#8217;, &#8216;c&#8217;, &#8216;d&#8217;], [&#8220;ei&#8221;, &#8220;zf&#8221;, &#8220;ei&#8221;, &#8220;am&#8221;], [&#8220;abcd&#8221;, &#8220;acbd&#8221;, &#8220;adbc&#8221;, &#8220;badc&#8221;, &#8220;dacb&#8221;, &#8220;cadb&#8221;, &#8220;cbda&#8221;, &#8220;abad&#8221;]); encrypter.encrypt(&#8220;abcd&#8221;); \/\/ return &#8220;eizfeiam&#8221;. &nbsp; \/\/ &#8216;a&#8217; maps to &#8220;ei&#8221;, &#8216;b&#8217; maps to &#8220;zf&#8221;, &#8216;c&#8217; maps to &#8220;ei&#8221;, and &#8216;d&#8217; maps to &#8220;am&#8221;. encrypter.decrypt(&#8220;eizfeiam&#8221;); \/\/ return 2. \/\/ &#8220;ei&#8221; can map to &#8216;a&#8217; or &#8216;c&#8217;, &#8220;zf&#8221; maps to &#8216;b&#8217;, and &#8220;am&#8221; maps to &#8216;d&#8217;. \/\/ Thus, the possible strings after decryption are &#8220;abad&#8221;, &#8220;cbad&#8221;, &#8220;abcd&#8221;, and &#8220;cbcd&#8221;. \/\/ 2 of those strings, &#8220;abad&#8221; and &#8220;abcd&#8221;, appear in dictionary, so the answer is 2.<\/p>\n\n\n\n<p><strong>Constraints:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>1 &lt;= keys.length == values.length &lt;= 26<\/code><\/li><li><code>values[i].length == 2<\/code><\/li><li><code>1 &lt;= dictionary.length &lt;= 100<\/code><\/li><li><code>1 &lt;= dictionary[i].length &lt;= 100<\/code><\/li><li>All&nbsp;<code>keys[i]<\/code>&nbsp;and&nbsp;<code>dictionary[i]<\/code>&nbsp;are&nbsp;<strong>unique<\/strong>.<\/li><li><code>1 &lt;= word1.length &lt;= 2000<\/code><\/li><li><code>1 &lt;= word2.length &lt;= 200<\/code><\/li><li>All&nbsp;<code>word1[i]<\/code>&nbsp;appear in&nbsp;<code>keys<\/code>.<\/li><li><code>word2.length<\/code>&nbsp;is even.<\/li><li><code>keys<\/code>,&nbsp;<code>values[i]<\/code>,&nbsp;<code>dictionary[i]<\/code>,&nbsp;<code>word1<\/code>, and&nbsp;<code>word2<\/code>&nbsp;only contain lowercase English letters.<\/li><li>At most&nbsp;<code>200<\/code>&nbsp;calls will be made to&nbsp;<code>encrypt<\/code>&nbsp;and&nbsp;<code>decrypt<\/code>&nbsp;<strong>in total<\/strong>.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Solution: <\/strong><\/h2>\n\n\n\n<p>For encryption, follow the instruction. Time complexity: O(len(word)) = O(2000)<br>For decryption, try all words in the dictionary and encrypt them and compare the encrypted string with the word to decrypt. Time <meta charset=\"utf-8\">complexity: O(sum(len(word_in_dict))) = O(100*100)<\/p>\n\n\n\n<p>Worst case: 200 calls to decryption, T = 200 * O(100 * 100) = O(2*10<sup>6<\/sup>)<\/p>\n\n\n\n<div class=\"responsive-tabs\">\n<h2 class=\"tabtitle\">C++<\/h2>\n<div class=\"tabcontent\">\n\n<pre lang=\"c++\">\n\/\/ Author: Huahua\nclass Encrypter {\npublic:\n  Encrypter(vector<char>& keys, \n            vector<string>& values, \n            vector<string>& dictionary):\n        vals(26),\n        dict(dictionary) {\n    for (size_t i = 0; i < keys.size(); ++i)\n      vals[keys[i] - 'a'] = values[i];  \n  }\n\n  string encrypt(string word1) {\n    string ans;\n    for (char c : word1)\n      ans += vals[c - 'a'];\n    return ans;\n  }\n\n  int decrypt(string word2) {\n    return count_if(begin(dict), end(dict), [&#038;](const string&#038; w){ \n      return encrypt(w) == word2;\n    });    \n  }\nprivate:\n  vector<string> vals;\n  vector<string> dict;\n};\n<\/pre>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Optimization<\/strong><\/h2>\n\n\n\n<p>Pre-compute answer for all the words in dictionary.<\/p>\n\n\n\n<p>decrypt: Time complexity: O(1)<\/p>\n\n\n\n<div class=\"responsive-tabs\">\n<h2 class=\"tabtitle\">C++<\/h2>\n<div class=\"tabcontent\">\n\n<pre lang=\"c++\">\n\/\/ Author: Huahua\nclass Encrypter {\npublic:\n  Encrypter(vector<char>& keys, \n            vector<string>& values, \n            vector<string>& dictionary):\n        vals(26) {\n    for (size_t i = 0; i < keys.size(); ++i)\n      vals[keys[i] - 'a'] = values[i];  \n    for (const string&#038; w : dictionary)\n      ++counts[encrypt(w)];\n  }\n\n  string encrypt(string word1) {\n    string ans;\n    for (char c : word1)\n      ans += vals[c - 'a'];\n    return ans;\n  }\n\n  int decrypt(string word2) {\n    auto it = counts.find(word2);\n    return it == counts.end() ? 0 : it->second;\n  }\nprivate:\n  vector<string> vals;  \n  unordered_map<string, int> counts;\n};\n<\/pre>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>You are given a character array&nbsp;keys&nbsp;containing&nbsp;unique&nbsp;characters and a string array&nbsp;values&nbsp;containing strings of length 2. You are also given another string array&nbsp;dictionary&nbsp;that contains all permitted original&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[89],"tags":[291,773,217,4],"class_list":["post-9626","post","type-post","status-publish","format-standard","hentry","category-data-structure","tag-data-structure","tag-dictionary","tag-hard","tag-string","entry","simple"],"_links":{"self":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/9626","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/comments?post=9626"}],"version-history":[{"count":3,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/9626\/revisions"}],"predecessor-version":[{"id":9631,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/9626\/revisions\/9631"}],"wp:attachment":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/media?parent=9626"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/categories?post=9626"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/tags?post=9626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}