<?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>kmp Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/kmp/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/kmp/</link>
	<description></description>
	<lastBuildDate>Sun, 21 Feb 2021 01:39:52 +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>kmp Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/kmp/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>花花酱 LeetCode 1764. Form Array by Concatenating Subarrays of Another Array</title>
		<link>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-1764-form-array-by-concatenating-subarrays-of-another-array/</link>
					<comments>https://zxi.mytechroad.com/blog/algorithms/array/leetcode-1764-form-array-by-concatenating-subarrays-of-another-array/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 21 Feb 2021 00:32:23 +0000</pubDate>
				<category><![CDATA[Array]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[kmp]]></category>
		<category><![CDATA[matching]]></category>
		<category><![CDATA[prefix]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=8131</guid>

					<description><![CDATA[<p>You are given a 2D integer array&#160;groups&#160;of length&#160;n. You are also given an integer array&#160;nums. You are asked if you can choose&#160;n&#160;disjoint&#160;subarrays from the array&#160;nums&#160;such&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-1764-form-array-by-concatenating-subarrays-of-another-array/">花花酱 LeetCode 1764. Form Array by Concatenating Subarrays of Another Array</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 2D integer array&nbsp;<code>groups</code>&nbsp;of length&nbsp;<code>n</code>. You are also given an integer array&nbsp;<code>nums</code>.</p>



<p>You are asked if you can choose&nbsp;<code>n</code>&nbsp;<strong>disjoint&nbsp;</strong>subarrays from the array&nbsp;<code>nums</code>&nbsp;such that the&nbsp;<code>i<sup>th</sup></code>&nbsp;subarray is equal to&nbsp;<code>groups[i]</code>&nbsp;(<strong>0-indexed</strong>), and if&nbsp;<code>i &gt; 0</code>, the&nbsp;<code>(i-1)<sup>th</sup></code>&nbsp;subarray appears&nbsp;<strong>before</strong>&nbsp;the&nbsp;<code>i<sup>th</sup></code>&nbsp;subarray in&nbsp;<code>nums</code>&nbsp;(i.e. the subarrays must be in the same order as&nbsp;<code>groups</code>).</p>



<p>Return&nbsp;<code>true</code>&nbsp;<em>if you can do this task, and</em>&nbsp;<code>false</code>&nbsp;<em>otherwise</em>.</p>



<p>Note that the subarrays are&nbsp;<strong>disjoint</strong>&nbsp;if and only if there is no index&nbsp;<code>k</code>&nbsp;such that&nbsp;<code>nums[k]</code>&nbsp;belongs to more than one subarray. A subarray is a contiguous sequence of elements within an array.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> groups = [[1,-1,-1],[3,-2,0]], nums = [1,-1,0,1,-1,-1,3,-2,0]
<strong>Output:</strong> true
<strong>Explanation:</strong> You can choose the 0<sup>th</sup> subarray as [1,-1,0,<strong>1,-1,-1</strong>,3,-2,0] and the 1<sup>st</sup> one as [1,-1,0,1,-1,-1,<strong>3,-2,0</strong>].
These subarrays are disjoint as they share no common nums[k] element.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> groups = [[10,-2],[1,2,3,4]], nums = [1,2,3,4,10,-2]
<strong>Output:</strong> false
<strong>Explanation: </strong>Note that choosing the subarrays [<strong>1,2,3,4</strong>,10,-2] and [1,2,3,4,<strong>10,-2</strong>] is incorrect because they are not in the same order as in groups.
[10,-2] must come before [1,2,3,4].
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> groups = [[1,2,3],[3,4]], nums = [7,7,1,2,3,4,7,7]
<strong>Output:</strong> false
<strong>Explanation: </strong>Note that choosing the subarrays [7,7,<strong>1,2,3</strong>,4,7,7] and [7,7,1,2,<strong>3,4</strong>,7,7] is invalid because they are not disjoint.
They share a common elements nums[4] (0-indexed).
</pre>



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



<ul><li><code>groups.length == n</code></li><li><code>1 &lt;= n &lt;= 10<sup>3</sup></code></li><li><code>1 &lt;= groups[i].length, sum(groups[i].length) &lt;= 10<sup>3</sup></code></li><li><code>1 &lt;= nums.length &lt;= 10<sup>3</sup></code></li><li><code>-10<sup>7</sup>&nbsp;&lt;= groups[i][j], nums[k] &lt;= 10<sup>7</sup></code></li></ul>



<p></p>



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



<p>Time complexity: O(n^2?)<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:
  bool canChoose(vector&lt;vector&lt;int&gt;&gt;&amp; groups, vector&lt;int&gt;&amp; nums) {
    const int n = nums.size();
    int s = 0;
    for (const auto&amp; g : groups) {
      bool found = false;
      for (int i = s; i &lt;= n - g.size(); ++i)
        if (equal(begin(g), end(g), begin(nums) + i)) {
          s = i + g.size();
          found = true;
          break;
        }
      if (!found) return false;
    }
    return true;
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/algorithms/array/leetcode-1764-form-array-by-concatenating-subarrays-of-another-array/">花花酱 LeetCode 1764. Form Array by Concatenating Subarrays of Another Array</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-1764-form-array-by-concatenating-subarrays-of-another-array/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-6639389865eb5405055149/] [crayon-6639389865eb9833892553/] Applications LeetCode 28. strStr() [crayon-6639389865ebb601208819/] LeetCode 459.&#160;Repeated Substring Pattern [crayon-6639389865ebc624959816/] 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 1392. Longest Happy Prefix</title>
		<link>https://zxi.mytechroad.com/blog/string/leetcode-1392-longest-happy-prefix/</link>
					<comments>https://zxi.mytechroad.com/blog/string/leetcode-1392-longest-happy-prefix/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 22 Mar 2020 05:37:00 +0000</pubDate>
				<category><![CDATA[String]]></category>
		<category><![CDATA[hard]]></category>
		<category><![CDATA[kmp]]></category>
		<category><![CDATA[rolling hash]]></category>
		<category><![CDATA[string]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=6523</guid>

					<description><![CDATA[<p>A string is called a&#160;happy prefix&#160;if is a&#160;non-empty&#160;prefix which is also a suffix (excluding itself). Given a string&#160;s. Return the&#160;longest happy prefix&#160;of&#160;s&#160;. Return an empty&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-1392-longest-happy-prefix/">花花酱 LeetCode 1392. Longest Happy Prefix</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>A string is called a&nbsp;<em>happy prefix</em>&nbsp;if is a&nbsp;<strong>non-empty</strong>&nbsp;prefix which is also a suffix (excluding itself).</p>



<p>Given a string&nbsp;<code>s</code>. Return the&nbsp;<strong>longest happy prefix</strong>&nbsp;of&nbsp;<code>s</code>&nbsp;.</p>



<p>Return an empty string if no such prefix exists.</p>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "level"
<strong>Output:</strong> "l"
<strong>Explanation:</strong> s contains 4 prefix excluding itself ("l", "le", "lev", "leve"), and suffix ("l", "el", "vel", "evel"). The largest prefix which is also suffix is given by "l".
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "ababab"
<strong>Output:</strong> "abab"
<strong>Explanation:</strong> "abab" is the largest prefix which is also suffix. They can overlap in the original string.
</pre>



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



<pre class="wp-block-preformatted;crayon:false"><strong>Input:</strong> s = "leetcodeleet"
<strong>Output:</strong> "leet"
</pre>



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



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



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



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



<h2><strong>Solution: Rolling Hash</strong></h2>



<p>Time complexity: O(n) / worst case: O(n^2)<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 longestPrefix(string_view s) {
    const int kMod = 16769023;
    const int kBase = 128;
    const int n = s.length();
    int p = 0;
    int q = 0;
    int a = 1;
    int ans = 0;
    for (int i = 1; i &lt; n; ++i) {
      p = (p + a * s[i - 1]) % kMod;
      q = (q * kBase + s[n - i]) % kMod;      
      a = (a * kBase) % kMod;
      if (p == q &amp;&amp; s.substr(0, i) == s.substr(n - i))
        ans = i;
    }
    return string(s.substr(0, ans));
  }
};</pre>
</div></div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/string/leetcode-1392-longest-happy-prefix/">花花酱 LeetCode 1392. Longest Happy Prefix</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-1392-longest-happy-prefix/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
