<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>suffix Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/suffix/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/suffix/</link>
	<description></description>
	<lastBuildDate>Mon, 02 May 2022 04:50:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.8</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>suffix Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/suffix/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 2256. Minimum Average Difference</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2256-minimum-average-difference/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2256-minimum-average-difference/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 02 May 2022 04:49:42 +0000</pubDate>
				<category><![CDATA[Array]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[suffix]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9707</guid>

					<description><![CDATA[<p>You are given a&#160;0-indexed&#160;integer array&#160;nums&#160;of length&#160;n. The&#160;average difference&#160;of the index&#160;i&#160;is the&#160;absolute&#160;difference&#160;between the average of the&#160;first&#160;i + 1&#160;elements of&#160;nums&#160;and the average of the&#160;last&#160;n - i -&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2256-minimum-average-difference/">花花酱 LeetCode 2256. Minimum Average Difference</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You are given a&nbsp;<strong>0-indexed</strong>&nbsp;integer array&nbsp;<code>nums</code>&nbsp;of length&nbsp;<code>n</code>.</p>



<p>The&nbsp;<strong>average difference</strong>&nbsp;of the index&nbsp;<code>i</code>&nbsp;is the&nbsp;<strong>absolute</strong>&nbsp;<strong>difference</strong>&nbsp;between the average of the&nbsp;<strong>first</strong>&nbsp;<code>i + 1</code>&nbsp;elements of&nbsp;<code>nums</code>&nbsp;and the average of the&nbsp;<strong>last</strong>&nbsp;<code>n - i - 1</code>&nbsp;elements. Both averages should be&nbsp;<strong>rounded down</strong>&nbsp;to the nearest integer.</p>



<p>Return<em>&nbsp;the index with the&nbsp;<strong>minimum average difference</strong></em>. If there are multiple such indices, return the&nbsp;<strong>smallest</strong>&nbsp;one.</p>



<p><strong>Note:</strong></p>



<ul><li>The&nbsp;<strong>absolute difference</strong>&nbsp;of two numbers is the absolute value of their difference.</li><li>The&nbsp;<strong>average</strong>&nbsp;of&nbsp;<code>n</code>&nbsp;elements is the&nbsp;<strong>sum</strong>&nbsp;of the&nbsp;<code>n</code>&nbsp;elements divided (<strong>integer division</strong>) by&nbsp;<code>n</code>.</li><li>The average of&nbsp;<code>0</code>&nbsp;elements is considered to be&nbsp;<code>0</code>.</li></ul>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [2,5,3,9,5,3]
<strong>Output:</strong> 3
<strong>Explanation:</strong>
- The average difference of index 0 is: |2 / 1 - (5 + 3 + 9 + 5 + 3) / 5| = |2 / 1 - 25 / 5| = |2 - 5| = 3.
- The average difference of index 1 is: |(2 + 5) / 2 - (3 + 9 + 5 + 3) / 4| = |7 / 2 - 20 / 4| = |3 - 5| = 2.
- The average difference of index 2 is: |(2 + 5 + 3) / 3 - (9 + 5 + 3) / 3| = |10 / 3 - 17 / 3| = |3 - 5| = 2.
- The average difference of index 3 is: |(2 + 5 + 3 + 9) / 4 - (5 + 3) / 2| = |19 / 4 - 8 / 2| = |4 - 4| = 0.
- The average difference of index 4 is: |(2 + 5 + 3 + 9 + 5) / 5 - 3 / 1| = |24 / 5 - 3 / 1| = |4 - 3| = 1.
- The average difference of index 5 is: |(2 + 5 + 3 + 9 + 5 + 3) / 6 - 0| = |27 / 6 - 0| = |4 - 0| = 4.
The average difference of index 3 is the minimum average difference so return 3.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> nums = [0]
<strong>Output:</strong> 0
<strong>Explanation:</strong>
The only index is 0 so return 0.
The average difference of index 0 is: |0 / 1 - 0| = |0 - 0| = 0.
</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li><li><code>0 &lt;= nums[i] &lt;= 10<sup>5</sup></code></li></ul>



<p>Solution: Prefix / Suffix Sum</p>



<p>Time complexity: O(n)<br>Space complexity: O(1)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int minimumAverageDifference(vector&lt;int&gt;&amp; nums) {
    const int n = nums.size();
    long long suffix = accumulate(begin(nums), end(nums), 0LL);
    long long prefix = 0;
    int best = INT_MAX;
    int ans = 0;
    for (int i = 0; i &lt; n; ++i) {
      prefix += nums[i];
      suffix -= nums[i];
      int cur = abs(prefix / (i + 1) - (i == n - 1 ? 0 : suffix / (n - i - 1)));
      if (cur &lt; best) {
        best = cur;
        ans = i;
      }
    }
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2256-minimum-average-difference/">花花酱 LeetCode 2256. Minimum Average Difference</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2256-minimum-average-difference/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 2100. Find Good Days to Rob the Bank</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2100-find-good-days-to-rob-the-bank/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2100-find-good-days-to-rob-the-bank/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 12 Dec 2021 18:54:07 +0000</pubDate>
				<category><![CDATA[Array]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[medium]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[suffix]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=9136</guid>

					<description><![CDATA[<p>You and a gang of thieves are planning on robbing a bank. You are given a&#160;0-indexed&#160;integer array&#160;security, where&#160;security[i]&#160;is the number of guards on duty on&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2100-find-good-days-to-rob-the-bank/">花花酱 LeetCode 2100. Find Good Days to Rob the Bank</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>You and a gang of thieves are planning on robbing a bank. You are given a&nbsp;<strong>0-indexed</strong>&nbsp;integer array&nbsp;<code>security</code>, where&nbsp;<code>security[i]</code>&nbsp;is the number of guards on duty on the&nbsp;<code>i<sup>th</sup></code>&nbsp;day. The days are numbered starting from&nbsp;<code>0</code>. You are also given an integer&nbsp;<code>time</code>.</p>



<p>The&nbsp;<code>i<sup>th</sup></code>&nbsp;day is a good day to rob the bank if:</p>



<ul><li>There are at least&nbsp;<code>time</code>&nbsp;days before and after the&nbsp;<code>i<sup>th</sup></code>&nbsp;day,</li><li>The number of guards at the bank for the&nbsp;<code>time</code>&nbsp;days&nbsp;<strong>before</strong>&nbsp;<code>i</code>&nbsp;are&nbsp;<strong>non-increasing</strong>, and</li><li>The number of guards at the bank for the&nbsp;<code>time</code>&nbsp;days&nbsp;<strong>after</strong>&nbsp;<code>i</code>&nbsp;are&nbsp;<strong>non-decreasing</strong>.</li></ul>



<p>More formally, this means day&nbsp;<code>i</code>&nbsp;is a good day to rob the bank if and only if&nbsp;<code>security[i - time] &gt;= security[i - time + 1] &gt;= ... &gt;= security[i] &lt;= ... &lt;= security[i + time - 1] &lt;= security[i + time]</code>.</p>



<p>Return&nbsp;<em>a list of&nbsp;<strong>all</strong>&nbsp;days&nbsp;<strong>(0-indexed)&nbsp;</strong>that are good days to rob the bank</em>.<em>&nbsp;The order that the days are returned in does<strong>&nbsp;</strong><strong>not</strong>&nbsp;matter.</em></p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> security = [5,3,3,3,5,6,2], time = 2
<strong>Output:</strong> [2,3]
<strong>Explanation:</strong>
On day 2, we have security[0] &gt;= security[1] &gt;= security[2] &lt;= security[3] &lt;= security[4].
On day 3, we have security[1] &gt;= security[2] &gt;= security[3] &lt;= security[4] &lt;= security[5].
No other days satisfy this condition, so days 2 and 3 are the only good days to rob the bank.
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> security = [1,1,1,1,1], time = 0
<strong>Output:</strong> [0,1,2,3,4]
<strong>Explanation:</strong>
Since time equals 0, every day is a good day to rob the bank, so return every day.
</pre>



<p><strong>Example 3:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> security = [1,2,3,4,5,6], time = 2
<strong>Output:</strong> []
<strong>Explanation:</strong>
No day has 2 days before it that have a non-increasing number of guards.
Thus, no day is a good day to rob the bank, so return an empty list.
</pre>



<p><strong>Example 4:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> security = [1], time = 5
<strong>Output:</strong> []
<strong>Explanation:</strong>
No day has 5 days before and after it.
Thus, no day is a good day to rob the bank, so return an empty list.</pre>



<p><strong>Constraints:</strong></p>



<ul><li><code>1 &lt;= security.length &lt;= 10<sup>5</sup></code></li><li><code>0 &lt;= security[i], time &lt;= 10<sup>5</sup></code></li></ul>



<h2><strong>Solution: Pre-Processing</strong></h2>



<p>Pre-compute the non-increasing days at days[i] and the non-decreasing days at days[i] using prefix and suffix arrays.</p>



<p>Time complexity: O(n)<br>Space complexity: O(n)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  vector&lt;int&gt; goodDaysToRobBank(vector&lt;int&gt;&amp; security, int time) {
    const int n = security.size();
    vector&lt;int&gt; before(n);
    vector&lt;int&gt; after(n);
    for (int i = 1; i &lt; n; ++i)
      before[i] = security[i - 1] &gt;= security[i] ? before[i - 1] + 1 : 0;
    for (int i = n - 2; i &gt;= 0; --i)
      after[i] = security[i + 1] &gt;= security[i] ? after[i + 1] + 1 : 0;
    vector&lt;int&gt; ans;
    for (int i = time; i + time &lt; n; ++i)
      if (before[i] &gt;= time &amp;&amp; after[i] &gt;= time)
        ans.push_back(i);
    return ans;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2100-find-good-days-to-rob-the-bank/">花花酱 LeetCode 2100. Find Good Days to Rob the Bank</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-2100-find-good-days-to-rob-the-bank/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>KMP Algorithm SP19</title>
		<link>https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Wed, 01 Apr 2020 03:29:45 +0000</pubDate>
				<category><![CDATA[SP]]></category>
		<category><![CDATA[kmp]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[suffix]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6556</guid>

					<description><![CDATA[<p>KMP Algorithm, KMP 字符串搜索算法 Time complexity: O(m+n)Space complexity: O(m) Implementation [crayon-663cad15b80f0049206802/] [crayon-663cad15b80f3734543780/] Applications LeetCode 28. strStr() [crayon-663cad15b80f9671263114/] LeetCode 459.&#160;Repeated Substring Pattern [crayon-663cad15b80fe333578986/] 1392.&#160;Longest Happy Prefix&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/">KMP Algorithm SP19</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="花花酱 KMP Algorithm - 刷题找工作 SP19" width="500" height="375" src="https://www.youtube.com/embed/uKr9qIZMtzw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>KMP Algorithm, KMP 字符串搜索算法</p>



<p>Time complexity: O(m+n)<br>Space complexity: O(m)</p>



<h2><strong>Implementation</strong></h2>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

// Author: Huahua
namespace KMP {
vector&lt;int&gt; Build(const string&amp; p) {
  const int m = p.length();
  vector&lt;int&gt; nxt{0, 0};
  for (int i = 1, j = 0; i &lt; m; ++i) {
    while (j &gt; 0 &amp;&amp; p[i] != p[j])
      j = nxt[j];
    if (p[i] == p[j])
      ++j;
    nxt.push_back(j);
  }
  return nxt;
}

vector&lt;int&gt; Match(const string&amp; s, const string&amp; p) {
  vector&lt;int&gt; nxt(Build(p));
  vector&lt;int&gt; ans;
  const int n = s.length();
  const int m = p.length();
  for (int i = 0, j = 0; i &lt; n; ++i) {
    while (j &gt; 0 &amp;&amp; s[i] != p[j])
      j = nxt[j];
    if (s[i] == p[j])
      ++j;
    if (j == m) {
      ans.push_back(i - m + 1);
      j = nxt[j];
    }
  }
  return ans;
}
};  // namespace KMP

void CheckEQ(const vector&lt;int&gt;&amp; actual, const vector&lt;int&gt;&amp; expected) {
  if (actual != expected) {
    std::cout &lt;&lt; &quot;expected:&quot;;
    for (int v : expected)
      std::cout &lt;&lt; &quot; &quot; &lt;&lt; v;
    std::cout &lt;&lt; &quot; actual:&quot;;
    for (int v : actual)
      std::cout &lt;&lt; &quot; &quot; &lt;&lt; v;
    std::cout &lt;&lt; std::endl;
  } else {
    std::cout &lt;&lt; &quot;PASS&quot; &lt;&lt; std::endl;
  }
}

int main(int argc, char** argv) {
  CheckEQ(KMP::Build(&quot;ABCDABD&quot;), {0, 0, 0, 0, 0, 1, 2, 0});
  CheckEQ(KMP::Build(&quot;AB&quot;), {0, 0, 0});
  CheckEQ(KMP::Build(&quot;A&quot;), {0, 0});
  CheckEQ(KMP::Build(&quot;AA&quot;), {0, 0, 1});
  CheckEQ(KMP::Build(&quot;AAA&quot;), {0, 0, 1, 2});
  CheckEQ(KMP::Build(&quot;AABA&quot;), {0, 0, 1, 0, 1});
  CheckEQ(KMP::Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;ABCDABD&quot;), {15});
  CheckEQ(KMP::Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;AB&quot;), {0, 4, 8, 11, 15, 19});
  CheckEQ(KMP::Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;B&quot;), {1, 5, 9, 12, 16, 20});
  CheckEQ(KMP::Match(&quot;AAAAA&quot;, &quot;A&quot;), {0, 1, 2, 3, 4});
  CheckEQ(KMP::Match(&quot;AAAAA&quot;, &quot;AA&quot;), {0, 1, 2, 3});
  CheckEQ(KMP::Match(&quot;AAAAA&quot;, &quot;AAA&quot;), {0, 1, 2});
  CheckEQ(KMP::Match(&quot;ABC&quot;, &quot;ABC&quot;), {0});
  return 0;
}</pre>

</div><h2 class="tabtitle">Python3</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">#!/usr/bin/env python3
from typing import List

# Author: Huahua


def Build(p: str) -&gt; List[int]:
    m = len(p)
    nxt = [0, 0]
    j = 0
    for i in range(1, m):
        while j &gt; 0 and p[i] != p[j]:
            j = nxt[j]
        if p[i] == p[j]:
            j += 1
        nxt.append(j)
    return nxt


def Match(s: str, p: str) -&gt; List[int]:
    n, m = len(s), len(p)
    nxt = Build(p)
    ans = []
    j = 0
    for i in range(n):
        while j &gt; 0 and s[i] != p[j]:
            j = nxt[j]
        if s[i] == p[j]:
            j += 1
        if j == m:
            ans.append(i - m + 1)
            j = nxt[j]
    return ans


def CheckEQ(actual, expected):
    if actual != expected:
        print('actual: %s, expected: %s' % (actual, expected))
    else:
        print('Pass')


if __name__ == &quot;__main__&quot;:
    CheckEQ(Build(&quot;ABCDABD&quot;), [0, 0, 0, 0, 0, 1, 2, 0])
    CheckEQ(Build(&quot;AB&quot;), [0, 0, 0])
    CheckEQ(Build(&quot;A&quot;), [0, 0])
    CheckEQ(Build(&quot;AA&quot;), [0, 0, 1])
    CheckEQ(Build(&quot;AAAA&quot;), [0, 0, 1, 2, 3])
    CheckEQ(Build(&quot;AABA&quot;), [0, 0, 1, 0, 1])
    CheckEQ(Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;ABCDABD&quot;), [15])
    CheckEQ(Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;AB&quot;), [0, 4, 8, 11, 15, 19])
    CheckEQ(Match(&quot;ABC ABCDAB ABCDABCDABDE&quot;, &quot;B&quot;), [1, 5, 9, 12, 16, 20])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;A&quot;), [0, 1, 2, 3, 4])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;AA&quot;), [0, 1, 2, 3])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;AAAA&quot;), [0, 1])
    CheckEQ(Match(&quot;AAAAA&quot;, &quot;AAAAA&quot;), [0])
    CheckEQ(Match(&quot;AABAABA&quot;, &quot;AABA&quot;), [0, 3])</pre>
</div></div>



<h2><strong>Applications</strong></h2>



<p>LeetCode 28. strStr()</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  int strStr(string haystack, string needle) {
    if (needle.empty()) return 0;
    auto matches = KMP::Match(haystack, needle);
    return matches.empty() ? -1 : matches[0];
  }
};</pre>
</div></div>



<p>LeetCode 459.&nbsp;Repeated Substring Pattern</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  bool repeatedSubstringPattern(string str) {
    const int n = str.length();
    auto nxt = KMP::Build(str);
    return nxt[n] &amp;amp;&amp;amp; nxt[n] % (n - nxt[n]) == 0;
  }
};</pre>
</div></div>



<p><a href="https://zxi.mytechroad.com/blog/string/leetcode-1392-longest-happy-prefix/">1392.&nbsp;Longest Happy Prefix</a></p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  string longestPrefix(const string&amp;amp; s) {    
    return s.substr(0, KMP::Build(s).back());
  }
};</pre>
</div></div>



<p></p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/">KMP Algorithm SP19</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/sp/kmp-algorithm-sp19/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 1163. Last Substring in Lexicographical Order</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-1163-last-substring-in-lexicographical-order/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-1163-last-substring-in-lexicographical-order/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 18 Aug 2019 16:01:27 +0000</pubDate>
				<category><![CDATA[String]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[suffix]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=5450</guid>

					<description><![CDATA[<p>Given a string&#160;s, return the last substring of&#160;s&#160;in lexicographical order. Example 1: Input: "abab" Output: "bab" Explanation: The substrings are ["a", "ab", "aba", "abab", "b",&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-1163-last-substring-in-lexicographical-order/">花花酱 LeetCode 1163. Last Substring in Lexicographical Order</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Given a string&nbsp;<code>s</code>, return the last substring of&nbsp;<code>s</code>&nbsp;in lexicographical order.</p>



<p><strong>Example 1:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input: </strong>"abab"
<strong>Output: </strong>"bab"
<strong>Explanation: </strong>The substrings are ["a", "ab", "aba", "abab", "b", "ba", "bab"]. The lexicographically maximum substring is "bab".
</pre>



<p><strong>Example 2:</strong></p>



<pre class="wp-block-preformatted;crayon:false"><strong>Input: </strong>"leetcode"
<strong>Output: </strong>"tcode"
</pre>



<p><strong>Note:</strong></p>



<ol><li><code>1 &lt;= s.length &lt;= 10^5</code></li><li>s&nbsp;contains only lowercase English letters.</li></ol>



<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>



<h2><strong>Solution 1: Brute Force</strong></h2>



<p>Try all possible suffixes.<br>Time complexity: O(n^2)<br>Space complexity: O(1)<br></p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua, 452 ms, 12.8 MB
class Solution {
public:
  string lastSubstring(string_view s) {
    string_view ans;
    for (int i = 0; i &lt; s.length(); ++i)
      if (s.substr(i) &gt; ans) ans = s.substr(i);
    return string(ans);
  }
};</pre>
</div></div>



<h2><strong>Solution 2: Keep max and compare with candidates</strong></h2>



<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>



<p>e.g. &#8220;acbacbc&#8221;</p>



<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>



<p>Time complexity: O(n)<br>Space complexity: O(1)</p>



<div class="responsive-tabs">
<h2 class="tabtitle">C++</h2>
<div class="tabcontent">

<pre class="crayon-plain-tag">// Author: Huahua
class Solution {
public:
  string lastSubstring(string s) {
    int max_i = 0;
    char max_c = 0;
    int cand_i = 0;
    int l = 0;
    
    for (int i = 0; i &lt; s.length(); ++i) {
      if (s[i] &gt; max_c) {
        // Find a better starting point.
        max_c = s[i];
        max_i = i;
        cand_i = -1;
        l = 1;
      } else if (cand_i != -1) {
        // Has a candidate.
        if (s[i] &gt; s[max_i + l]) {
          // The candidate is larger.
          max_i = cand_i;
          cand_i = -1;
        } else if (s[i] == s[max_i + l]) {
          // The candidate is the same as current best.
          ++l;
        } else {
          // The candidate is smaller, no longer needed.
          cand_i = -1;
        }
      } else if (s[i] == max_c) {
        // Find a new candidate, starting with length 1.
        cand_i = i;
        l = 1;
      } 
    }
    
    return s.substr(max_i);
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-1163-last-substring-in-lexicographical-order/">花花酱 LeetCode 1163. Last Substring in Lexicographical Order</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/string/leetcode-1163-last-substring-in-lexicographical-order/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 820. Short Encoding of Words</title>
		<link>https://zxi.mytechroad.com/blog/hashtable/leetcode-820-short-encoding-of-words/</link>
					<comments>https://zxi.mytechroad.com/blog/hashtable/leetcode-820-short-encoding-of-words/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Tue, 24 Apr 2018 07:45:28 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[hashset]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[suffix]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=2760</guid>

					<description><![CDATA[<p>Problem Given a list of words, we may encode it by writing a reference string S and a list of indexes A. For example, if the list of&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-820-short-encoding-of-words/">花花酱 LeetCode 820. Short Encoding of Words</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1><strong>Problem</strong></h1>
<p>Given a list of words, we may encode it by writing a reference string <code>S</code> and a list of indexes <code>A</code>.</p>
<p>For example, if the list of words is <code>["time", "me", "bell"]</code>, we can write it as <code>S = "time#bell#"</code> and <code>indexes = [0, 2, 5]</code>.</p>
<p>Then for each index, we will recover the word by reading from the reference string from that index until we reach a &#8220;#&#8221; character.</p>
<p>What is the length of the shortest reference string S possible that encodes the given words?</p>
<p><strong>Example:</strong></p>
<pre class="crayon:false"><strong>Input:</strong> words = <code>["time", "me", "bell"]</code> <strong>Output:</strong> 10 <strong>Explanation:</strong> S = <code>"time#bell#" and indexes = [0, 2, 5</code>].</pre>
<p><strong>Note:</strong></p>
<ol>
<li><code>1 &lt;= words.length &lt;= 2000.</code></li>
<li><code>1 &lt;= words[i].length &lt;= 7.</code></li>
<li>Each word has only lowercase letters.</li>
</ol>
<h1><strong>Idea</strong></h1>
<p>Remove all the words that are suffix of other words.</p>
<h1><strong>Solution</strong></h1>
<p>Time complexity: O(n*l^2)</p>
<p>Space complexity: O(n*l)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 43 ms
class Solution {
public:
  int minimumLengthEncoding(vector&lt;string&gt;&amp; words) {
    unordered_set&lt;string&gt; s(words.begin(), words.end());
    for (const string&amp; w : words) {
      for (int i = w.length() - 1; i &gt; 0; --i)        
        s.erase(w.substr(i));
    }
    int ans = 0;
    for (const string&amp; w : s)
      ans += w.length() + 1;
    return ans;
  }
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/hashtable/leetcode-820-short-encoding-of-words/">花花酱 LeetCode 820. Short Encoding of Words</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/hashtable/leetcode-820-short-encoding-of-words/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 745. Prefix and Suffix Search</title>
		<link>https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/</link>
					<comments>https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Mon, 11 Dec 2017 23:33:34 +0000</pubDate>
				<category><![CDATA[Hashtable]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[Tree]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[suffix]]></category>
		<category><![CDATA[trie]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1184</guid>

					<description><![CDATA[<p>Link: https://leetcode.com/problems/prefix-and-suffix-search/description/ Problem: Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordFilter.f(String prefix, String suffix). It will return the word with given prefix and suffix with maximum weight. If no&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/">花花酱 LeetCode 745. Prefix and Suffix Search</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Link: <a href="https://leetcode.com/problems/prefix-and-suffix-search/description/">https://leetcode.com/problems/prefix-and-suffix-search/description/</a></p>
<p><iframe width="500" height="375" src="https://www.youtube.com/embed/a-4WbFqalIA?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p><strong>Problem:</strong></p>
<p>Given many <code>words</code>, <code>words[i]</code> has weight <code>i</code>.</p>
<p>Design a class <code>WordFilter</code> that supports one function, <code>WordFilter.f(String prefix, String suffix)</code>. It will return the word with given <code>prefix</code> and <code>suffix</code> with maximum weight. If no word exists, return -1.</p>
<p><b>Examples:</b></p><pre class="crayon-plain-tag">Input:
WordFilter([&quot;apple&quot;])
WordFilter.f(&quot;a&quot;, &quot;e&quot;) // returns 0
WordFilter.f(&quot;b&quot;, &quot;&quot;) // returns -1</pre><p><b>Note:</b></p>
<ol>
<li><code>words</code> has length in range <code>[1, 15000]</code>.</li>
<li>For each test case, up to <code>words.length</code> queries <code>WordFilter.f</code> may be made.</li>
<li><code>words[i]</code> has length in range <code>[1, 10]</code>.</li>
<li><code>prefix, suffix</code> have lengths in range <code>[0, 10]</code>.</li>
<li><code>words[i]</code> and <code>prefix, suffix</code> queries consist of lowercase letters only.</li>
</ol>
<p><strong>Idea:</strong></p>
<p>Construct all possible filters</p>
<p>&nbsp;</p>
<p><strong>Solution1:</strong></p>
<p>C++</p>
<p>Time complexity: O(NL^3 + QL)  where N is the number of words, L is the max length of the word, Q is the number of queries.</p>
<p>Space complexity: O(NL^3)</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 482 ms
class WordFilter {
public:
    WordFilter(const vector&lt;string&gt;&amp; words) {
        int index = 0;
        for (const string&amp; word : words) {
            int n = word.length();
            string prefix;
            for (int i = 0; i &lt;= n; ++i) {
                if (i &gt; 0) prefix += word[i - 1];
                string suffix;
                for (int j = n; j &gt;= 0; --j) {                    
                    if (j != n) suffix = word[j] + suffix;
                    const string key = prefix + "_" + suffix;
                    filters_[key] = index;                    
                }                
            }
            ++index;
        }
    }
    
    int f(string prefix, string suffix) {
        const string key = prefix + "_" + suffix;
        auto it = filters_.find(key);
        if (it != filters_.end()) return it-&gt;second;
        return -1;
    }
private:
    unordered_map&lt;string, int&gt; filters_;
};</pre><p>Version #2</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 499 ms
class WordFilter {
public:
    WordFilter(const vector&lt;string&gt;&amp; words) {
        int index = 0;
        for (const string&amp; word : words) {
            int n = word.length();
            vector&lt;string&gt; prefixes(n + 1, "");
            vector&lt;string&gt; suffixes(n + 1, "");
            for (int i = 0; i &lt; n; ++i) {
                prefixes[i + 1] = prefixes[i] + word[i];
                suffixes[i + 1] = word[n - i - 1] + suffixes[i];
            }
            
            for (const string&amp; prefix : prefixes)          
                for (const string&amp; suffix : suffixes)                              
                    filters_[prefix + "_" + suffix] = index;            
            ++index;
        }        
    }
    
    int f(string prefix, string suffix) {
        const string key = prefix + "_" + suffix;
        auto it = filters_.find(key);
        if (it != filters_.end()) return it-&gt;second;
        return -1;
    }
private:
    unordered_map&lt;string, int&gt; filters_;
};</pre><p><strong>Solution 2</strong>:</p>
<p>C++ / Trie</p>
<p>Time complexity: O(NL^2 + QL)  where N is the number of words, L is the max length of the word, Q is the number of queries.</p>
<p>Space complexity: O(NL^2)</p><pre class="crayon-plain-tag">// Author: Huahua
// Runtime: 572 ms
class Trie {
public:
    /** Initialize your data structure here. */
    Trie(): root_(new TrieNode()) {}
    
    /** Inserts a word into the trie. */
    void insert(const string&amp; word, int index) {
        TrieNode* p = root_.get();
        for (const char c : word) {            
            if (!p-&gt;children[c - 'a'])
                p-&gt;children[c - 'a'] = new TrieNode();
            p = p-&gt;children[c - 'a'];
            // Update index
            p-&gt;index = index;
        }
        p-&gt;is_word = true;
    }
    
    
    /** Returns the index of word that has the prefix. */
    int startsWith(const string&amp; prefix) const {
        auto node = find(prefix);
        if (!node) return -1;
        return node-&gt;index;
    }
private:
    struct TrieNode {
        TrieNode():index(-1), is_word(false), children(27, nullptr){}
        
        ~TrieNode() {
            for (TrieNode* child : children)
                if (child) delete child;
        }
        
        int index;
        int is_word;
        vector&lt;TrieNode*&gt; children;
    };
    
    const TrieNode* find(const string&amp; prefix) const {
        const TrieNode* p = root_.get();
        for (const char c : prefix) {
            p = p-&gt;children[c - 'a'];
            if (p == nullptr) break;
        }
        return p;
    }
    
    std::unique_ptr&lt;TrieNode&gt; root_;
};

class WordFilter {
public:
    WordFilter(vector&lt;string&gt; words) {        
        for (int i = 0; i &lt; words.size(); ++i) {
            const string&amp; w = words[i];            
            string key = "{" + w;
            trie_.insert(key, i);            
            for (int j = 0; j &lt; w.size(); ++j) {
                key = w[w.size() - j - 1] + key;                
                trie_.insert(key, i);
            }
        }
    }
    
    int f(string prefix, string suffix) {        
        return trie_.startsWith(suffix + "{" + prefix);
    }
private:
    Trie trie_;
};</pre><p><strong>Related Problems:</strong></p>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/hashtable/leetcode-676-implement-magic-dictionary/">[解题报告] LeetCode 676. Implement Magic Dictionary</a></li>
<li><a href="http://zxi.mytechroad.com/blog/data-structure/leetcode-208-implement-trie-prefix-tree/">[解题报告] LeetCode 208. Implement Trie (Prefix Tree)</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/">花花酱 LeetCode 745. Prefix and Suffix Search</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/tree/leetcode-745-prefix-and-suffix-search/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
