{"id":5450,"date":"2019-08-18T09:01:27","date_gmt":"2019-08-18T16:01:27","guid":{"rendered":"https:\/\/zxi.mytechroad.com\/blog\/?p=5450"},"modified":"2019-08-18T09:51:20","modified_gmt":"2019-08-18T16:51:20","slug":"leetcode-1163-last-substring-in-lexicographical-order","status":"publish","type":"post","link":"https:\/\/zxi.mytechroad.com\/blog\/string\/leetcode-1163-last-substring-in-lexicographical-order\/","title":{"rendered":"\u82b1\u82b1\u9171 LeetCode 1163. Last Substring in Lexicographical Order"},"content":{"rendered":"\n<p>Given a string&nbsp;<code>s<\/code>, return the last substring of&nbsp;<code>s<\/code>&nbsp;in lexicographical order.<\/p>\n\n\n\n<p><strong>Example 1:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input: <\/strong>\"abab\"\n<strong>Output: <\/strong>\"bab\"\n<strong>Explanation: <\/strong>The substrings are [\"a\", \"ab\", \"aba\", \"abab\", \"b\", \"ba\", \"bab\"]. The lexicographically maximum substring is \"bab\".\n<\/pre>\n\n\n\n<p><strong>Example 2:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted;crayon:false\"><strong>Input: <\/strong>\"leetcode\"\n<strong>Output: <\/strong>\"tcode\"\n<\/pre>\n\n\n\n<p><strong>Note:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><code>1 &lt;= s.length &lt;= 10^5<\/code><\/li><li>s&nbsp;contains only lowercase English letters.<\/li><\/ol>\n\n\n\n<p>Key observation: The last substring must be a suffix of the original string, can&#8217;t a substring in the middle since we can always extend it.<br>e.g. leetcode -&gt; tcode, can&#8217;t be &#8220;t&#8221;, &#8220;tc&#8221;, &#8220;tco&#8221;, &#8220;tcod&#8221;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Solution 1: Brute Force<\/strong><\/h2>\n\n\n\n<p>Try all possible suffixes.<br>Time complexity: O(n^2)<br>Space complexity: O(1)<br><\/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, 452 ms, 12.8 MB\nclass Solution {\npublic:\n  string lastSubstring(string_view s) {\n    string_view ans;\n    for (int i = 0; i < s.length(); ++i)\n      if (s.substr(i) > ans) ans = s.substr(i);\n    return string(ans);\n  }\n};\n<\/pre>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Solution 2: Keep max and compare with candidates<\/strong><\/h2>\n\n\n\n<p>Find the first largest letter as a starting point, whenever there is a same letter, keep it as a candidate and compare with the current best. If the later is larger, take over the current best.<\/p>\n\n\n\n<p>e.g. &#8220;acbacbc&#8221;<\/p>\n\n\n\n<p> &#8220;c&#8221; > &#8220;a&#8221;, the first &#8220;c&#8221; becomes the best.<br>&#8220;c&#8221; = &#8220;c&#8221;, the second &#8220;c&#8221; becomes a candidate<br>starting compare best and candidate.<br>&#8220;cb&#8221; = &#8220;cb&#8221;<br>&#8220;cba&#8221; &lt; &#8220;cbc&#8221;, cand_i is the new best.<br><\/p>\n\n\n\n<p>Time complexity: O(n)<br>Space 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 Solution {\npublic:\n  string lastSubstring(string s) {\n    int max_i = 0;\n    char max_c = 0;\n    int cand_i = 0;\n    int l = 0;\n    \n    for (int i = 0; i < s.length(); ++i) {\n      if (s[i] > max_c) {\n        \/\/ Find a better starting point.\n        max_c = s[i];\n        max_i = i;\n        cand_i = -1;\n        l = 1;\n      } else if (cand_i != -1) {\n        \/\/ Has a candidate.\n        if (s[i] > s[max_i + l]) {\n          \/\/ The candidate is larger.\n          max_i = cand_i;\n          cand_i = -1;\n        } else if (s[i] == s[max_i + l]) {\n          \/\/ The candidate is the same as current best.\n          ++l;\n        } else {\n          \/\/ The candidate is smaller, no longer needed.\n          cand_i = -1;\n        }\n      } else if (s[i] == max_c) {\n        \/\/ Find a new candidate, starting with length 1.\n        cand_i = i;\n        l = 1;\n      } \n    }\n    \n    return s.substr(max_i);\n  }\n};\n<\/pre>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Given a string&nbsp;s, return the last substring of&nbsp;s&nbsp;in lexicographical order. Example 1: Input: &#8220;abab&#8221; Output: &#8220;bab&#8221; Explanation: The substrings are [&#8220;a&#8221;, &#8220;ab&#8221;, &#8220;aba&#8221;, &#8220;abab&#8221;, &#8220;b&#8221;,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[47],"tags":[217,186],"class_list":["post-5450","post","type-post","status-publish","format-standard","hentry","category-string","tag-hard","tag-suffix","entry","simple"],"_links":{"self":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/5450","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=5450"}],"version-history":[{"count":3,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/5450\/revisions"}],"predecessor-version":[{"id":5453,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/posts\/5450\/revisions\/5453"}],"wp:attachment":[{"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/media?parent=5450"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/categories?post=5450"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zxi.mytechroad.com\/blog\/wp-json\/wp\/v2\/tags?post=5450"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}