<?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>Morris-Pratt algorithm &#8211; stoimen&#039;s web log</title>
	<atom:link href="/tag/morris-pratt-algorithm/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>on web development</description>
	<lastBuildDate>Tue, 13 Feb 2018 08:18:15 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.0.3</generator>
	<item>
		<title>Computer Algorithms: Boyer-Moore String Searching</title>
		<link>/2012/04/17/computer-algorithms-boyer-moore-string-search-and-matching/</link>
		<comments>/2012/04/17/computer-algorithms-boyer-moore-string-search-and-matching/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 08:24:46 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[Boyer–Moore string search algorithm]]></category>
		<category><![CDATA[Boyer–Moore–Horspool algorithm]]></category>
		<category><![CDATA[Computer programming]]></category>
		<category><![CDATA[Computer science]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[J Strother Moore]]></category>
		<category><![CDATA[Morris-Pratt algorithm]]></category>
		<category><![CDATA[natural language search]]></category>
		<category><![CDATA[pattern forward]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Rabin-Karp algorithm]]></category>
		<category><![CDATA[Rabin-Karp string search algorithm]]></category>
		<category><![CDATA[Robert S. Boyer]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[String searching algorithm]]></category>
		<category><![CDATA[string searching algorithms]]></category>
		<category><![CDATA[Strlen]]></category>
		<category><![CDATA[Substring]]></category>

		<guid isPermaLink="false">/?p=3049</guid>
		<description><![CDATA[Introduction Have you ever asked yourself which is the algorithm used to find a word after clicking Ctrl+F and typing something? Well I guess you know the answer from the title, but in this article you’ll find out how exactly this is done. As we saw from the Morris-Pratt string searching we don’t need to &#8230; <a href="/2012/04/17/computer-algorithms-boyer-moore-string-search-and-matching/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Boyer-Moore String Searching</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/04/09/computer-algorithms-morris-pratt-string-searching/" rel="bookmark" title="Computer Algorithms: Morris-Pratt String Searching">Computer Algorithms: Morris-Pratt String Searching </a></li>
<li><a href="/2012/04/02/computer-algorithms-rabin-karp-string-searching/" rel="bookmark" title="Computer Algorithms: Rabin-Karp String Searching">Computer Algorithms: Rabin-Karp String Searching </a></li>
<li><a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" rel="bookmark" title="Computer Algorithms: Brute Force String Matching">Computer Algorithms: Brute Force String Matching </a></li>
<li><a href="/2011/11/24/computer-algorithms-sequential-search/" rel="bookmark" title="Computer Algorithms: Sequential Search">Computer Algorithms: Sequential Search </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Have you ever asked yourself which is the algorithm used to find a word after clicking Ctrl+F and typing something? Well I guess you know the answer from the title, but in this article you’ll find out how exactly this is done.</p>
<p>As we saw from the <a href="/2012/04/09/computer-algorithms-morris-pratt-string-searching/" title="Computer Algorithms: Morris-Pratt String Searching">Morris-Pratt string searching</a> we don’t need to compare the text and the pattern character by character. Some comparisons can be skipped in order to improve the performance of the string searching. Indeed the <a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" title="Computer Algorithms: Brute Force String Matching">brute force string searching</a> and the <a href="/2012/04/02/computer-algorithms-rabin-karp-string-searching/" title="Computer Algorithms: Rabin-Karp String Searching">Rabin-Karp algorithm</a> are quite slow only because they compare the pattern and the text character by character.</p>
<p>In the other hand the Morris-Pratt algorithm is a very good improvement of the brute force string searching, but the question remains. Is there any algorithm that is faster than Morris-Pratt &#8211; is there any way to skip more comparisons and to move the pattern faster.</p>
<p>It’s clear that if we have to find whether a single character is contained into a text we need at least &#8220;n&#8221; steps, where n is the length of the text. Once we have to find whether a pattern with the length of &#8220;m&#8221; is contained into a text with length of &#8220;n&#8221; the case is getting a little more complex.</p>
<p>However the answer is that there is such algorithm that is faster and more suitable than Morris-Pratt. This is the Boyer-Moore string searching.</p>
<h2>Overview</h2>
<p>Boyer-Moore is an algorithm that improves the performance of pattern searching into a text by considering some observations. It is defined in 1977 by <a href="http://en.wikipedia.org/wiki/Robert_S._Boyer" title="Robert S. Boyer" target="_blank">Robert S. Boyer</a> and <a href="http://en.wikipedia.org/wiki/J_Strother_Moore" title="J Strother Moore" target="_blank">J Strother Moore</a> and it consist of some specific features. </p>
<p>First of all this algorithm starts comparing the pattern from the leftmost part of text and moves it to the right, as on the picture below.</p>
<p><figure id="attachment_3059" style="width: 618px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreShiftingDirection.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreShiftingDirection.png" alt="Boyer-Moore Shifting Direction" title="Boyer-Moore Shifting Direction" width="618" height="153" class="size-full wp-image-3059" srcset="/wp-content/uploads/2012/04/Boyer-MooreShiftingDirection.png 618w, /wp-content/uploads/2012/04/Boyer-MooreShiftingDirection-300x74.png 300w" sizes="(max-width: 618px) 100vw, 618px" /></a><figcaption class="wp-caption-text">In Boyer-Moore the pattern is shifted from left to right!</figcaption></figure><span id="more-3049"></span></p>
<p>Unlike other string searching algorithms though, Boyer-Moore compares the pattern against a possible match from right to left as shown below.</p>
<figure id="attachment_3066" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreComparisonModel.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreComparisonModel.png" alt="Boyer-Moore Comparison Model" title="Boyer-Moore Comparison Model" width="622" height="169" class="size-full wp-image-3066" srcset="/wp-content/uploads/2012/04/Boyer-MooreComparisonModel.png 622w, /wp-content/uploads/2012/04/Boyer-MooreComparisonModel-300x81.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text">Unlike other algorithms the letters of the pattern are compared from right to left!</figcaption></figure>
<p>The main idea of Boyer-Moore in order to improve the performance are some observations of the pattern. In the terminology of this algorithm they are called good-suffix and bad-character shifts. Let’s see by the following examples what they are standing for.</p>
<h3>Good-suffix Shifts</h3>
<p>Just like the Morris-Pratt algorithm we start to compare the pattern against some portion of the text where a possible match will occur. In Boyer-Moore as I said this is done from the rightmost letter of the pattern. After some characters have matched we find a mismatch.</p>
<figure id="attachment_3065" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreAMismatch.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreAMismatch.png" alt="Boyer-Moore a Mismatch" title="Boyer-Moore a Mismatch" width="622" height="214" class="size-full wp-image-3065" srcset="/wp-content/uploads/2012/04/Boyer-MooreAMismatch.png 622w, /wp-content/uploads/2012/04/Boyer-MooreAMismatch-300x103.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text"> </figcaption></figure>
<p>So how can we move the pattern to the right in order to skip unusual comparisons. To answer this question we need to explore the pattern. Let’s say there is a portion of the pattern that is repeated inside the pattern itself, like it is shown on the picture below.</p>
<figure id="attachment_3062" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreGood-suffixShift1.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreGood-suffixShift1.png" alt="Boyer-Moore Good-suffix Shift 1" title="Boyer-Moore Good-suffix Shift 1" width="622" height="195" class="size-full wp-image-3062" srcset="/wp-content/uploads/2012/04/Boyer-MooreGood-suffixShift1.png 622w, /wp-content/uploads/2012/04/Boyer-MooreGood-suffixShift1-300x94.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text">The pattern may consist of repeating portions of characters!</figcaption></figure>
<p>In this case we must move the pattern thus the repeated portion must now align with its first occurrence in the pattern.</p>
<p>A variation of this case is when the portion from the pattern A overlaps with another portion that consists of the same characters.</p>
<figure id="attachment_3061" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift2.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift2.png" alt="Boyer-Moore Good Suffix Shift 2" title="Boyer-Moore Good Suffix Shift 2" width="622" height="195" class="size-full wp-image-3061" srcset="/wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift2.png 622w, /wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift2-300x94.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text">Sometimes these portions may overlap!</figcaption></figure>
<p>Yet again the shift must align the second portion with its first occurrence. </p>
<p>Finally only a portion of A, let’s say &#8220;B&#8221;, can happen to occur in the very beginning of the pattern, as on the diagram below.</p>
<figure id="attachment_3060" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift3.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift3.png" alt="Boyer-Moore Good Suffix Shift 3" title="Boyer-Moore Good Suffix Shift 3" width="622" height="195" class="size-full wp-image-3060" srcset="/wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift3.png 622w, /wp-content/uploads/2012/04/Boyer-MooreGoodSuffixShift3-300x94.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text">Only a sub-string of the pattern may re-occur at its front!</figcaption></figure>
<p>Now we must align the left end of the pattern with the rightmost occurrence of &#8220;B&#8221;.</p>
<h3>Bad Character Shifts</h3>
<p>Beside the good-suffix shifts the Boyer-Moore algorithm make use of the so called bad-character shifts. In case of a mismatch we can skip comparisons in case the character in the text doesn’t happen to appear in the pattern. To become clearer let’s see the following examples.</p>
<figure id="attachment_3064" style="width: 623px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreBadCharacter1.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreBadCharacter1.png" alt="Boyer-Moore Bad Character 1" title="Boyer-Moore Bad Character 1" width="623" height="237" class="size-full wp-image-3064" srcset="/wp-content/uploads/2012/04/Boyer-MooreBadCharacter1.png 623w, /wp-content/uploads/2012/04/Boyer-MooreBadCharacter1-300x114.png 300w" sizes="(max-width: 623px) 100vw, 623px" /></a><figcaption class="wp-caption-text">If the mismatched letter of the text appears in the pattern only in its front we can align it easily!</figcaption></figure>
<p>In the picture above we see that the mismatched character &#8220;B&#8221; from the text appears only in the beginning of the pattern. Thus we can simply shift the pattern to the right and align both characters B, skipping comparisons. An even better case is described by the following diagram where the mismatched letter isn’t contained into the pattern at all. Then we can shift forward the whole pattern.</p>
<figure id="attachment_3063" style="width: 623px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreBadCharacter2.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreBadCharacter2.png" alt="Boyer-Moore Bad Character 2" title="Boyer-Moore Bad Character 2" width="623" height="237" class="size-full wp-image-3063" srcset="/wp-content/uploads/2012/04/Boyer-MooreBadCharacter2.png 623w, /wp-content/uploads/2012/04/Boyer-MooreBadCharacter2-300x114.png 300w" sizes="(max-width: 623px) 100vw, 623px" /></a><figcaption class="wp-caption-text">In case the mismatched letter isn&#039;t contained into the pattern we move forward the pattern!</figcaption></figure>
<h3>Maximum of Good-suffix and Bad-Character shifts</h3>
<p>Boyer-Moore needs both good-suffix and bad-character shifts in order to speed up searching performance. After a mismatch the maximum of both is considered in order to move the pattern to the right.</p>
<h2>Complexity</h2>
<p>It&#8217;s clear that Boyer-Moore is faster than Morris-Pratt, but actually its worst-case complexity is O(n+m). The thing is that in natural language search Boyer-Moore does pretty well.</p>
<figure id="attachment_3073" style="width: 600px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-Moore-Complexity.png"><img src="/wp-content/uploads/2012/04/Boyer-Moore-Complexity.png" alt="Boyer-Moore Complexity" title="Boyer-Moore Complexity" width="600" height="371" class="size-full wp-image-3073" srcset="/wp-content/uploads/2012/04/Boyer-Moore-Complexity.png 600w, /wp-content/uploads/2012/04/Boyer-Moore-Complexity-300x185.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a><figcaption class="wp-caption-text">Worst-case scenario of Boyer-Moore - O(m+n)</figcaption></figure>
<h2>Implementation</h2>
<p>Finally let’s see the implementation in <a href="/category/php/" title="PHP on stoimen.com">PHP</a>, which can be easily &#8220;transcribed&#8221; into any other programming language. The only thing we need is the structures for bad-character shifts and good-suffixes shifts.</p>
<pre lang="PHP">
<?php

/**
 * Pattern we're searching for
 *
 * @var string
 */
$pattern = 'gloria';

/**
 * The text we're searching in
 *
 * @var string
 */
$text = 'Sic transit gloria mundi, non transit gloria Gundi!';

/**
 * Calculates the suffixes for a given pattern
 *
 * @param string $pattern
 * @param array  $suffixes
 */
function suffixes($pattern, &#038;$suffixes)
{
   $m = strlen($pattern);

   $suffixes[$m - 1] = $m;
   $g = $m - 1;

   for ($i = $m - 2; $i >= 0; --$i) {
      if ($i > $g && $suffixes[$i + $m - 1 - $f] < $i - $g) {
         $suffixes[$i] = $suffixes[$i + $m - 1 - $f];
      } else {
         if ($i < $g) {
            $g = $i;
         }
         $f = $i;
         	
         while ($g >= 0 && $pattern[$g] == $pattern[$g + $m - 1 - $f]) {
            $g--;
         }
         $suffixes[$i] = $f - $g;
      }
   }
}

/**
 * Fills in the array of bad characters.
 *
 * @param string $pattern
 * @param array  $badChars
 */
function badCharacters($pattern, &$badChars)
{
   $m = strlen($pattern);

   for ($i = 0; $i < $m - 1; ++$i) {
      $badChars[$pattern{$i}] = $m - $i - 1;
   }
}

/**
 * Fills in the array of good suffixes
 *
 * @param string $pattern
 * @param array  $goodSuffixes
 */
function goodSuffixes($pattern, &#038;$goodSuffixes)
{
   $m 		= strlen($pattern);
   $suff 	= array();

   suffixes($pattern, $suff);

   for ($i = 0; $i < $m; $i++) {
      $goodSuffixes[$i] = $m;
   }

   for ($i = $m - 1; $i >= 0; $i--) {
      if ($suff[$i] == $i + 1) {
         for ($j = 0; $j < $m - $i - 1; $j++) {
            if ($goodSuffixes[$j] == $m) {
               $goodSuffixes[$j] = $m - $i - 1;
            }
         }
      }
   }

   for ($i = 0; $i < $m - 2; $i++) {
      $goodSuffixes[$m - 1 - $suff[$i]] = $m - $i - 1;
   }
}

/**
 * Performs a search of the pattern into a given text
 *
 * @param string $pattern
 * @param string $text
 */
function boyer_moore($pattern, $text)
{
   $n = strlen($text);
   $m = strlen($pattern);

   $goodSuffixes 	= array();
   $badCharacters 	= array();

   goodSuffixes($pattern, &#038;$goodSuffixes);
   badCharacters($pattern, &#038;$badCharacters);

   $j = 0;
   while ($j < $n - $m) {
      for ($i = $m - 1; $i >= 0 && $pattern[$i] == $text[$i + $j]; $i--);
      if ($i < 0) {
         // note that if the substring occurs more
         // than once into the text, the algorithm will
         // print out each position of the substring
         echo $j;
         $j += $goodSuffixes[0];
      } else {
         $j += max($goodSuffixes[$i], $badCharacters[$text[$i + $j]] - $m + $i + 1);
      }
   }
}

// search using Boyer-Moore
// will return 12 and 38
boyer_moore($pattern, $text);
</pre>
<h2>Application</h2>
<p>Boyer-Moore is one of the most used string searching algorithm in practice. It is intuitively clear where it can be useful, but yet again I’ll say only that this algorithm is considered as the mostly used in practice for search and replace operations in text editors.</p>
<figure id="attachment_3068" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Boyer-MooreApplication.png"><img src="/wp-content/uploads/2012/04/Boyer-MooreApplication.png" alt="Boyer-Moore Application" title="Boyer-Moore Application" width="620" height="399" class="size-full wp-image-3068" srcset="/wp-content/uploads/2012/04/Boyer-MooreApplication.png 620w, /wp-content/uploads/2012/04/Boyer-MooreApplication-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text"> </figcaption></figure>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/04/09/computer-algorithms-morris-pratt-string-searching/" rel="bookmark" title="Computer Algorithms: Morris-Pratt String Searching">Computer Algorithms: Morris-Pratt String Searching </a></li>
<li><a href="/2012/04/02/computer-algorithms-rabin-karp-string-searching/" rel="bookmark" title="Computer Algorithms: Rabin-Karp String Searching">Computer Algorithms: Rabin-Karp String Searching </a></li>
<li><a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" rel="bookmark" title="Computer Algorithms: Brute Force String Matching">Computer Algorithms: Brute Force String Matching </a></li>
<li><a href="/2011/11/24/computer-algorithms-sequential-search/" rel="bookmark" title="Computer Algorithms: Sequential Search">Computer Algorithms: Sequential Search </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/04/17/computer-algorithms-boyer-moore-string-search-and-matching/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Morris-Pratt String Searching</title>
		<link>/2012/04/09/computer-algorithms-morris-pratt-string-searching/</link>
		<comments>/2012/04/09/computer-algorithms-morris-pratt-string-searching/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 19:41:05 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[Applied mathematics]]></category>
		<category><![CDATA[Boyer–Moore string search algorithm]]></category>
		<category><![CDATA[Brute-force search]]></category>
		<category><![CDATA[Complexity This algorithm]]></category>
		<category><![CDATA[Computer programming]]></category>
		<category><![CDATA[Computer science]]></category>
		<category><![CDATA[faster string searching algorithms]]></category>
		<category><![CDATA[James H. Morris]]></category>
		<category><![CDATA[Knuth–Morris–Pratt algorithm]]></category>
		<category><![CDATA[Lorem ipsum]]></category>
		<category><![CDATA[Morris-Pratt algorithm]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Rabin]]></category>
		<category><![CDATA[Rabin-Karp algorithm]]></category>
		<category><![CDATA[Rabin-Karp string search algorithm]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[String searching algorithm]]></category>
		<category><![CDATA[Vaughan Pratt]]></category>

		<guid isPermaLink="false">/?p=3019</guid>
		<description><![CDATA[Introduction We saw that neither brute force string searching nor Rabin-Karp string searching are effective. However in order to improve some algorithm, first we need to understand its principles in detail. We know already that brute force string matching is slow and we tried to improve it somehow by using a hash function in the &#8230; <a href="/2012/04/09/computer-algorithms-morris-pratt-string-searching/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Morris-Pratt String Searching</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/04/17/computer-algorithms-boyer-moore-string-search-and-matching/" rel="bookmark" title="Computer Algorithms: Boyer-Moore String Searching">Computer Algorithms: Boyer-Moore String Searching </a></li>
<li><a href="/2012/04/02/computer-algorithms-rabin-karp-string-searching/" rel="bookmark" title="Computer Algorithms: Rabin-Karp String Searching">Computer Algorithms: Rabin-Karp String Searching </a></li>
<li><a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" rel="bookmark" title="Computer Algorithms: Brute Force String Matching">Computer Algorithms: Brute Force String Matching </a></li>
<li><a href="/2011/08/18/powerful-php-less-known-string-manipulation/" rel="bookmark" title="Powerful PHP: Less Known String Manipulation">Powerful PHP: Less Known String Manipulation </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>We saw that neither <a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" title="Computer Algorithms: Brute Force String Matching">brute force string searching</a> nor <a href="/2012/04/02/computer-algorithms-rabin-karp-string-searching/" title="Computer Algorithms: Rabin-Karp String Searching">Rabin-Karp string searching</a> are effective. However in order to improve some algorithm, first we need to understand its principles in detail. We know already that brute force string matching is slow and we tried to improve it somehow by using a hash function in the Rabin-Karp algorithm. The problem is that Rabin-Karp has the same complexity as brute force string matching, which is O(mn).</p>
<p>Obviously we need a different approach, but to come with a different approach let’s see what’s wrong with brute force string searching. Indeed by taking a closer look at its principles we can answer the question. </p>
<p>In brute force matching we checked each character of the text with the first character of the pattern. In case of a match we shifted the comparison between the second character of the pattern and the next character of the text. The problem is that in case of a mismatch we must go several positions back in the text. Well in fact this technique can’t be optimized. </p>
<p><figure id="attachment_3025" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Morris-Pratt-brute-force-string-matching.png"><img src="/wp-content/uploads/2012/04/Morris-Pratt-brute-force-string-matching.png" alt="Morris-Pratt brute force string matching" title="Morris-Pratt brute force string matching" width="620" height="360" class="size-full wp-image-3025" srcset="/wp-content/uploads/2012/04/Morris-Pratt-brute-force-string-matching.png 620w, /wp-content/uploads/2012/04/Morris-Pratt-brute-force-string-matching-300x174.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">In brute force string matching in case of a mismatch we go back and we compare characters that has been compared already!</figcaption></figure><span id="more-3019"></span></p>
<p>As you can see on the picture above the problem is that once there is a mismatch we must rollback and start comparing from a position in the text that has been explored already. In our case we have checked the first, second, third and fourth letters, where there is a mismatch between the pattern and the text and then &#8230; we go back and start comparing from the second letter of the text.</p>
<p>This is completely useless, because we already know that the pattern begins with the letter “a” and no such letter happens to be between positions 1 and 3. So how can we improve this redundancy?</p>
<h2>Overview</h2>
<p>The answer of the question came to <a href="http://en.wikipedia.org/wiki/James_H._Morris" title="James H. Morris" target="_blank">James H. Morris</a> and <a href="http://en.wikipedia.org/wiki/Vaughan_Pratt" title="Vaughan Pratt" target="_blank">Vaughan Pratt</a> in 1977 when they described their algorithm, which by skipping lots of useless comparisons is more effective than brute force string matching. Let’s see it in detail. The only thing is to use the information gathered during the comparisons of the pattern and a possible match, as on the picture below.</p>
<figure id="attachment_3029" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Morris-Pratt-basic-principles.png"><img src="/wp-content/uploads/2012/04/Morris-Pratt-basic-principles.png" alt="Morris-Pratt basic principles" title="Morris-Pratt basic principles" width="620" height="483" class="size-full wp-image-3029" srcset="/wp-content/uploads/2012/04/Morris-Pratt-basic-principles.png 620w, /wp-content/uploads/2012/04/Morris-Pratt-basic-principles-300x233.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Morris-Pratt skips some comparisons by moving ahead to the next possible position of a match!</figcaption></figure>
<p>To do that first we have to preprocess the pattern in order to get possible positions for next matches. Thus after we start to find a possible match in case of a mismatch we’ll know exactly where we should jump in order to skip unusual comparisons.</p>
<h3>Generating the Table of Next Positions</h3>
<p>This is the tricky part in Morris-Pratt and that is how this algorithm overcomes the disadvantages of brute force string searching. Let&#8217;s see some pictures.</p>
<figure id="attachment_3044" style="width: 623px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Morris-Pratt-with-no-repeating-letters-in-the-pattern.png"><img src="/wp-content/uploads/2012/04/Morris-Pratt-with-no-repeating-letters-in-the-pattern.png" alt="Morris-Pratt with no repeating letters in the pattern" title="Morris-Pratt with no repeating letters in the pattern" width="623" height="361" class="size-full wp-image-3044" srcset="/wp-content/uploads/2012/04/Morris-Pratt-with-no-repeating-letters-in-the-pattern.png 623w, /wp-content/uploads/2012/04/Morris-Pratt-with-no-repeating-letters-in-the-pattern-300x173.png 300w" sizes="(max-width: 623px) 100vw, 623px" /></a><figcaption class="wp-caption-text">It is clear that if the pattern consists only of different letters in case of a mismatch we should start comparing the next character of the text with the first character of the pattern!</figcaption></figure>
<p>However in case of repeating character in the pattern if we have a mismatch after that character a possible match must begin from this repeating character, as on the picture bellow.</p>
<figure id="attachment_3045" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Morris-Pratt-with-one-repeating-letter-in-the-pattern.png"><img src="/wp-content/uploads/2012/04/Morris-Pratt-with-one-repeating-letter-in-the-pattern.png" alt="Morris-Pratt with one repeating letter in the pattern" title="Morris-Pratt with one repeating letter in the pattern" width="622" height="404" class="size-full wp-image-3045" srcset="/wp-content/uploads/2012/04/Morris-Pratt-with-one-repeating-letter-in-the-pattern.png 622w, /wp-content/uploads/2012/04/Morris-Pratt-with-one-repeating-letter-in-the-pattern-300x194.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text">The next table is slightly different if the pattern has repeating character! </figcaption></figure>
<p>Finally if there are more than one repeating character in the text the &#8220;next&#8221; table will consist show their position.</p>
<figure id="attachment_3046" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Morris-Pratt-more-than-one-repeating-letter-in-the-pattern.png"><img src="/wp-content/uploads/2012/04/Morris-Pratt-more-than-one-repeating-letter-in-the-pattern.png" alt="Morris-Pratt more than one repeating letter in the pattern" title="Morris-Pratt more than one repeating letter in the pattern" width="622" height="461" class="size-full wp-image-3046" srcset="/wp-content/uploads/2012/04/Morris-Pratt-more-than-one-repeating-letter-in-the-pattern.png 622w, /wp-content/uploads/2012/04/Morris-Pratt-more-than-one-repeating-letter-in-the-pattern-300x222.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text">The next table contains the positions of repeating letters!</figcaption></figure>
<p>After we have this table of possible “next” positions we can start exploring the text for our pattern.</p>
<figure id="attachment_3027" style="width: 622px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Morris-Pratt.png"><img src="/wp-content/uploads/2012/04/Morris-Pratt.png" alt="Morris-Pratt" title="Morris-Pratt" width="622" height="550" class="size-full wp-image-3027" srcset="/wp-content/uploads/2012/04/Morris-Pratt.png 622w, /wp-content/uploads/2012/04/Morris-Pratt-300x265.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></a><figcaption class="wp-caption-text"> </figcaption></figure>
<h2>Implementation</h2>
<p>Implementing Morris-Pratt isn’t difficult. First we have to preprocess the pattern and then perform the search. The following <a href="/category/php/" title="PHP on stoimen.com">PHP</a> code shows you how to do that.</p>
<pre lang="PHP">
/**
 * Pattern
 * 
 * @var string
 */
$pattern = 'mollis';

/**
 * Text to search
 * 
 * @var string
 */
$text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eleifend nisi viverra ipsum elementum porttitor quis at justo. Aliquam ligula felis, dignissim sit amet lobortis eget, lacinia ac augue. Quisque nec est elit, nec ultricies magna. Ut mi libero, dictum sit amet mollis non, aliquam et augue';

/**
 * Preprocess the pattern and return the "next" table
 * 
 * @param string $pattern
 */
function preprocessMorrisPratt($pattern, &$nextTable)
{
	$i = 0;
	$j = $nextTable[0] = -1;
	$len = strlen($pattern);
	
	while ($i < $len) {
		while ($j > -1 && $pattern[$i] != $pattern[$j]) {
			$j = $nextTable[$j];
		}
		
		$nextTable[++$i] = ++$j;
	}
}

/**
 * Performs a string search with the Morris-Pratt algorithm
 * 
 * @param string $text
 * @param string $pattern
 */
function MorrisPratt($text, $pattern)
{
	// get the text and pattern lengths
	$n = strlen($text);
	$m = strlen($pattern);
	$nextTable = array();
	
	// calculate the next table
	preprocessMorrisPratt($pattern, $nextTable);
	
	$i = $j = 0;
	while ($j < $n) {
		while ($i > -1 && $pattern[$i] != $text[$j]) {
			$i = $nextTable[$i];
		}
		$i++;
		$j++;
		if ($i >= $m) {
			return $j - $i;
		}
	}
	return -1;
}

// 275
echo MorrisPratt($text, $pattern);
</pre>
<h2>Complexity</h2>
<p>This algorithm needs some time and space for preprocessing. Thus the preprocess of the pattern can be done in O(m), where m is the length of the pattern, while the search itself needs O(m+n). The good news is that you can do the preprocess only once and then perform the search as many times as you wish!</p>
<p>The following chart shows the complexity O(n+m) compared with O(nm) for 5 letter patterns.</p>
<figure id="attachment_3026" style="width: 600px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Morris-Pratt-complexity.png"><img src="/wp-content/uploads/2012/04/Morris-Pratt-complexity.png" alt="Morris-Pratt complexity" title="Morris-Pratt complexity" width="600" height="371" class="size-full wp-image-3026" srcset="/wp-content/uploads/2012/04/Morris-Pratt-complexity.png 600w, /wp-content/uploads/2012/04/Morris-Pratt-complexity-300x185.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a><figcaption class="wp-caption-text">After pre-processing with O(m) the complexity of searching is O(n+m). You can see on the chart how effective is Morris-Pratt string searching compared to brute force string searching!</figcaption></figure>
<h2>Application</h2>
<h3>Why it&#8217;s cool</h3>
<ol>
<li>Its searching complexity is O(m+n) which is faster than brute force and Rabin-Karp</li>
<li>It’s fairly easy to implement</li>
</ol>
<h3>Why it isn’t cool</h3>
<ol>
<li>It needs additional space and time &#8211; O(m) for pre-processing</li>
<li>It can be optimized a bit (Knuth-Morris-Pratt)</li>
</ol>
<h2>Final Words</h2>
<p>Obviously this algorithm is quite useful because it improves in some very elegant manner the brute force matching. In the other hand you must know that there are faster string searching algorithms like the Boyer-Moore algorithm. However the Morris-Pratt algorithm can be quite useful in many cases, so understanding its principles can be very handy.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/04/17/computer-algorithms-boyer-moore-string-search-and-matching/" rel="bookmark" title="Computer Algorithms: Boyer-Moore String Searching">Computer Algorithms: Boyer-Moore String Searching </a></li>
<li><a href="/2012/04/02/computer-algorithms-rabin-karp-string-searching/" rel="bookmark" title="Computer Algorithms: Rabin-Karp String Searching">Computer Algorithms: Rabin-Karp String Searching </a></li>
<li><a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" rel="bookmark" title="Computer Algorithms: Brute Force String Matching">Computer Algorithms: Brute Force String Matching </a></li>
<li><a href="/2011/08/18/powerful-php-less-known-string-manipulation/" rel="bookmark" title="Powerful PHP: Less Known String Manipulation">Powerful PHP: Less Known String Manipulation </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/04/09/computer-algorithms-morris-pratt-string-searching/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
