<?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>search algorithms &#8211; stoimen&#039;s web log</title>
	<atom:link href="/tag/search-algorithms/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: Dijkstra Shortest Path in a Graph</title>
		<link>/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/</link>
		<comments>/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/#comments</comments>
		<pubDate>Mon, 15 Oct 2012 14:12:50 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[data structures]]></category>
		<category><![CDATA[Graphs]]></category>
		<category><![CDATA[BFS algorithm]]></category>
		<category><![CDATA[Breadth-first search]]></category>
		<category><![CDATA[Depth-first search]]></category>
		<category><![CDATA[Dijkstra algorithm]]></category>
		<category><![CDATA[Dijkstra's algorithm]]></category>
		<category><![CDATA[Distance]]></category>
		<category><![CDATA[Graph]]></category>
		<category><![CDATA[Graph theory]]></category>
		<category><![CDATA[library SPL]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Network theory]]></category>
		<category><![CDATA[path]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Routing algorithms]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[Shortest path problem]]></category>
		<category><![CDATA[The algorithm]]></category>
		<category><![CDATA[Theoretical computer science]]></category>
		<category><![CDATA[USD]]></category>

		<guid isPermaLink="false">/?p=3381</guid>
		<description><![CDATA[Introduction We already know how we can find the shortest paths in a graph starting from a given vertex. Practically we modified breadth-first search in order to calculate the distances from s to all other nodes reachable from s. We know that this works because BFS walks through the graph level by level. Some sources &#8230; <a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Dijkstra Shortest Path in a Graph</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
<li><a href="/2012/10/28/computer-algorithms-shortest-path-in-a-directed-acyclic-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Directed Acyclic Graph">Computer Algorithms: Shortest Path in a Directed Acyclic Graph </a></li>
<li><a href="/2012/10/22/computer-algorithms-bellman-ford-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Bellman-Ford Shortest Path in a Graph">Computer Algorithms: Bellman-Ford Shortest Path in a Graph </a></li>
<li><a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Breadth First Search">Computer Algorithms: Graph Breadth First Search </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>We already know how we can find the shortest paths in a graph starting from a given vertex. Practically we modified breadth-first search in order to calculate the distances from s to all other nodes reachable from s. We know that this works because BFS walks through the graph level by level.</p>
<figure id="attachment_3397" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/1.-BFS-Shortest-Paths.png"><img src="/wp-content/uploads/2012/10/1.-BFS-Shortest-Paths.png" alt="BFS Shortest Paths" title="BFS Shortest Paths" width="620" height="399" class="size-full wp-image-3397" srcset="/wp-content/uploads/2012/10/1.-BFS-Shortest-Paths.png 620w, /wp-content/uploads/2012/10/1.-BFS-Shortest-Paths-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">BFS is often used to find shortest paths between a starting node (s) and all other reachable nodes in a graph!</figcaption></figure>
<p>Some sources give a very simple explanation of how BFS finds the shortest paths in a graph. We must just think of the graph as a set of balls connected through strings. </p>
<figure id="attachment_3398" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/2.-The-Graph-as-Balls-and-Strings.png"><img src="/wp-content/uploads/2012/10/2.-The-Graph-as-Balls-and-Strings.png" alt="The Graph as Balls and Strings" title="The Graph as Balls and Strings" width="620" height="399" class="size-full wp-image-3398" srcset="/wp-content/uploads/2012/10/2.-The-Graph-as-Balls-and-Strings.png 620w, /wp-content/uploads/2012/10/2.-The-Graph-as-Balls-and-Strings-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">We can think of a graph as a set of balls connected through strings!</figcaption></figure>
<p>As we can see by lifting the ball called “S” all other balls fall down. The closest balls are directly connected to “s” and this is the first level, while the outermost balls are those with longest paths.</p>
<figure id="attachment_3399" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/3.-The-Graph-as-Balls-and-Strings-Levels.png"><img src="/wp-content/uploads/2012/10/3.-The-Graph-as-Balls-and-Strings-Levels.png" alt="The Graph as Balls and Strings Levels" title="The Graph as Balls and Strings Levels" width="620" height="399" class="size-full wp-image-3399" srcset="/wp-content/uploads/2012/10/3.-The-Graph-as-Balls-and-Strings-Levels.png 620w, /wp-content/uploads/2012/10/3.-The-Graph-as-Balls-and-Strings-Levels-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Breadth-first search works much like the image above &#8211; it explores the graph level by level, thus we&#8217;re sure that all the paths are the shortest!</figcaption></figure>
<p>Clearly edges like those between A and B doesn’t matter for our BFS algorithm because they don’t make the path from S to C through B shorter. This is also known as the triangle inequality, where the sum of the lengths of two of the sides of the triangle is always greater than the length of the third side.</p>
<figure id="attachment_3400" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/4.-Triangle-inequality.png"><img src="/wp-content/uploads/2012/10/4.-Triangle-inequality.png" alt="Triangle inequality" title="Triangle inequality" width="620" height="399" class="size-full wp-image-3400" srcset="/wp-content/uploads/2012/10/4.-Triangle-inequality.png 620w, /wp-content/uploads/2012/10/4.-Triangle-inequality-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">What the triangle inequality says us is that if we have a direct edge between two nodes &#8211; that must be the shortest path between them!</figcaption></figure>
<p>We must only answer the question is BFS the best algorithm that finds the shortest path between any two nodes of the graph? This is a reasonable question because as we know by using BFS we don’t find only the shortest path between given vertices i and j, but we also get the shortest paths between i and all other vertices of G. This is an information that we actually don’t need, but can we find the shortest path between i and j without that info?<span id="more-3381"></span></p>
<p>The answer is simply “no”! Practically depth-first search can’t help us. Even worse &#8211; we can find paths that are far not the shortest ones.</p>
<figure id="attachment_3401" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/5.-DFS-and-shortest-path.png"><img src="/wp-content/uploads/2012/10/5.-DFS-and-shortest-path.png" alt="DFS and shortest path" title="DFS and shortest path" width="620" height="399" class="size-full wp-image-3401" srcset="/wp-content/uploads/2012/10/5.-DFS-and-shortest-path.png 620w, /wp-content/uploads/2012/10/5.-DFS-and-shortest-path-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">DFS actually can find the longest path in some cases and can&#8217;t be used for finding shortest path!</figcaption></figure>
<p>In the image above using DFS the distance between 1 and 7 is 7 while practically there is an edge between them.</p>
<p>So BFS is the optimal algorithm for finding shortest paths in a graph. But there’s a catch! This algorithm works fine when we assume that all the edges are the same length. In the examples so far each edge has the value of 1. So N edges between s and i made the distance between them of a length N.</p>
<h2>Overview</h2>
<p>As we know in practice different edges can have different values. Exactly that was the case in weighted graphs. Going back to the road map example the distances between different cities are commonly evaluated in miles or kilometers. Of course we can associate any other meaningful value to this edges. This can be either time in hours to travel between cities, money for fuel or anything else.</p>
<figure id="attachment_3403" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/6.-Weighted-Graphs-in-Practice.png"><img src="/wp-content/uploads/2012/10/6.-Weighted-Graphs-in-Practice.png" alt="Weighted Graphs in Practice" title="Weighted Graphs in Practice" width="620" height="399" class="size-full wp-image-3403" srcset="/wp-content/uploads/2012/10/6.-Weighted-Graphs-in-Practice.png 620w, /wp-content/uploads/2012/10/6.-Weighted-Graphs-in-Practice-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">In practice is more common to use weighted graphs than non-weighted graphs!</figcaption></figure>
<p>Now BFS can’t help us any more. Why? Because using non-equal values for the edges the triangle inequality is no longer true. Now the edge (the direct path) between A and B can be greater than the sum of the two edges (A, C) + (C, B)!</p>
<figure id="attachment_3404" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/7.-Triangle-Inequality-Problem.png"><img src="/wp-content/uploads/2012/10/7.-Triangle-Inequality-Problem.png" alt="Triangle Inequality Problem" title="Triangle Inequality Problem" width="620" height="399" class="size-full wp-image-3404" srcset="/wp-content/uploads/2012/10/7.-Triangle-Inequality-Problem.png 620w, /wp-content/uploads/2012/10/7.-Triangle-Inequality-Problem-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">In a weighted graph the edges aren&#8217;t equal for our BFS algorithm so we can&#8217;t use it!</figcaption></figure>
<p>In other words, assuming the same abstraction with balls and wires the hanging wires can’t be discarded so easily.</p>
<figure id="attachment_3405" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/8.-The-Graph-as-Balls-and-Strings.png"><img src="/wp-content/uploads/2012/10/8.-The-Graph-as-Balls-and-Strings.png" alt="Weighted Graph as Balls and Strings" title="Weighted Graph as Balls and Strings" width="620" height="399" class="size-full wp-image-3405" srcset="/wp-content/uploads/2012/10/8.-The-Graph-as-Balls-and-Strings.png 620w, /wp-content/uploads/2012/10/8.-The-Graph-as-Balls-and-Strings-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">On weighted graphs BFS is no longer useful!</figcaption></figure>
<p>So now how can we solve this problem? A very dummy approach is to break apart each edge with dummy vertices in order to make BFS work again.</p>
<figure id="attachment_3406" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/9.-Breaking-apart-edges.png"><img src="/wp-content/uploads/2012/10/9.-Breaking-apart-edges.png" alt="Breaking apart edges" title="Breaking apart edges" width="620" height="399" class="size-full wp-image-3406" srcset="/wp-content/uploads/2012/10/9.-Breaking-apart-edges.png 620w, /wp-content/uploads/2012/10/9.-Breaking-apart-edges-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Since the graph is weighted we can decompose its edges to more &#8220;dummy&#8221; edges!</figcaption></figure>
<p>However this approach has several weak points. The major one is that we’ll have to keep much more information, which means more memory usage, for even small graphs. This is done in case we break each edge on too many parts.</p>
<p>The solution of this problem was given by <a href="http://en.wikipedia.org/wiki/Edsger_W._Dijkstra" title="Edsger W. Dijkstra" target="_blank">Edsger Dijkstra</a> in 1956 and published in 1959. The only thing we should do now is to be sure that even discarding the triangle inequality we have the shortest paths. The first thing to do is to keep information for the distance from s to the parent (previous) node of i in the graph in order to calculate which distance is shorter.</p>
<p>In BFS we used a queue in order to walk through all the ancestors of a node. This was made consecutively. Thus for the graph G on the next image the order of enqueuing the ancestors of S was A, B, C.</p>
<figure id="attachment_3409" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/10.-Order-of-enqueuing.png"><img src="/wp-content/uploads/2012/10/10.-Order-of-enqueuing.png" alt="Order of enqueuing" title="Order of enqueuing" width="620" height="399" class="size-full wp-image-3409" srcset="/wp-content/uploads/2012/10/10.-Order-of-enqueuing.png 620w, /wp-content/uploads/2012/10/10.-Order-of-enqueuing-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">The order of enqueuing in BFS is consecutive &#8211; something that isn&#8217;t working for weighted graphs!</figcaption></figure>
<p>The Dijkstra’s algorithm make use of a priority queue, also know as a heap. This fact combined by the fact we keep info for the shortest path so far help us find shortest paths in a weighted graphs.</p>
<p>Why this works? To answer this question let’s see the next very basic example, assuming the graph G from the next image. As we can see the triangle inequality isn’t true.</p>
<figure id="attachment_3410" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/11.-Weighted-graph.png"><img src="/wp-content/uploads/2012/10/11.-Weighted-graph.png" alt="Weighted graph" title="Weighted graph" width="620" height="399" class="size-full wp-image-3410" srcset="/wp-content/uploads/2012/10/11.-Weighted-graph.png 620w, /wp-content/uploads/2012/10/11.-Weighted-graph-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">A weighted graph that doesn&#8217;t follow the triangle inequality!</figcaption></figure>
<p>OK, we see that the path [S, B, A] is shorter than [S, A] although the edge (S, A) exists. How the Dijkstra algorithm overcomes this problem.</p>
<p>First we have no information about the distances (S, A) and (S, B), the only thing we know is that S is the starting point, its distance is 0 and its path so far is the empty set. So first we enqueue in a priority the distances from S to A and B.</p>
<figure id="attachment_3411" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/12.-Dijkstra-Priority-Queue.png"><img src="/wp-content/uploads/2012/10/12.-Dijkstra-Priority-Queue.png" alt="Dijkstra Priority Queue" title="Dijkstra Priority Queue" width="620" height="399" class="size-full wp-image-3411" srcset="/wp-content/uploads/2012/10/12.-Dijkstra-Priority-Queue.png 620w, /wp-content/uploads/2012/10/12.-Dijkstra-Priority-Queue-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">The algorithm of Dijkstra make use of a priority queue!</figcaption></figure>
<p>Now we dequeue the minimum (first in the heap) element from the queue &#8211; the closest node to S, which is B. Then all the nodes adjacent to S in the queue are tested for adjacency to B, thus if we have already the distance between S and A now we can test if its longer than (S, B) + (B, A) &#8211; the triangle inequality!</p>
<p>So far we know that we must change a bit BFS to get the Dijkstra algorithm. The only thing to do is to keep info for each node for the path through its parent and to use a priority queue.</p>
<h2>Code</h2>
<p>Implementing this algorithms isn’t much more difficult than BFS, so here’s the code in <a href="/category/php/" title="PHP on Stoimen.com">PHP</a>. However this example make use of the standard php library SPL and the PriorityQueue data structure, but any developer can code <a href="/2012/08/07/computer-algorithms-heap-and-heapsort-data-structure/" title="Computer Algorithms: Heap and Heapsort">his own heap</a>.</p>
<p>Here&#8217;s the graph from the code:</p>
<figure id="attachment_3413" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/0.-Graph.png"><img src="/wp-content/uploads/2012/10/0.-Graph.png" alt="The Graph from the Code" title="The Graph from the Code" width="620" height="399" class="size-full wp-image-3413" srcset="/wp-content/uploads/2012/10/0.-Graph.png 620w, /wp-content/uploads/2012/10/0.-Graph-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">The graph!</figcaption></figure>
<pre lang="PHP">
class vertex
{
    public $key         = null;
    public $visited     = 0;
    public $distance    = 1000000;  // infinite
    public $parent      = null;
    public $path        = null;
    
    public function __construct($key) 
    {
        $this->key  = $key;
    }
}

class PriorityQueue extends SplPriorityQueue
{
    public function compare($a, $b)
    {
        if ($a === $b) return 0;
        return $a > $b ? -1 : 1;
    }
}

$v0 = new vertex(0);
$v1 = new vertex(1);
$v2 = new vertex(2);
$v3 = new vertex(3);
$v4 = new vertex(4);
$v5 = new vertex(5);

$list0 = new SplDoublyLinkedList();
$list0->push(array('vertex' => $v1, 'distance' => 3));
$list0->push(array('vertex' => $v3, 'distance' => 1));
$list0->rewind();

$list1 = new SplDoublyLinkedList();
$list1->push(array('vertex' => $v0, 'distance' => 3));
$list1->push(array('vertex' => $v2, 'distance' => 7));
$list1->rewind();

$list2 = new SplDoublyLinkedList();
$list2->push(array('vertex' => $v1, 'distance' => 7));
$list2->push(array('vertex' => $v3, 'distance' => 8));
$list2->push(array('vertex' => $v4, 'distance' => 12));
$list2->rewind();

$list3 = new SplDoublyLinkedList();
$list3->push(array('vertex' => $v0, 'distance' => 1));
$list3->push(array('vertex' => $v2, 'distance' => 8));
$list3->rewind();

$list4 = new SplDoublyLinkedList();
$list4->push(array('vertex' => $v2, 'distance' => 12));
$list4->push(array('vertex' => $v5, 'distance' => 3));
$list4->rewind();

$list5 = new SplDoublyLinkedList();
$list5->push(array('vertex' => $v4, 'distance' => 3));
$list5->rewind();

$adjacencyList = array(
    $list0,
    $list1,
    $list2,
    $list3,
    $list4,
    $list5,
);

function calcShortestPaths(vertex $start, &$adjLists)
{
    // define an empty queue
    $q = new PriorityQueue();
    
    // push the starting vertex into the queue
    $q->insert($start, 0);
    $q->rewind();
    
    // mark the distance to it 0
    $start->distance = 0;
    
    // the path to the starting vertex
    $start->path = array($start->key);
    
    while ($q->valid()) {
        $t = $q->extract();
        $t->visited = 1;
        
        $l = $adjLists[$t->key];
        while ($l->valid()) {
            $item = $l->current();
            
            if (!$item['vertex']->visited) {
                if ($item['vertex']->distance > $t->distance + $item['distance']) {
                    $item['vertex']->distance = $t->distance + $item['distance'];
                    $item['vertex']->parent = $t;
                }
                
                $item['vertex']->path = array_merge($t->path, array($item['vertex']->key));
                
                $q->insert($item["vertex"], $item["vertex"]->distance);
            }
            $l->next();
        }
        $q->recoverFromCorruption();
        $q->rewind();
    }
}

calcShortestPaths($v0, $adjacencyList);

// The path from node 0 to node 5
// [0, 1, 2, 4, 5]
echo '[' . implode(', ', $v5->path) . ']';
</pre>
<h2>Complexity</h2>
<p>The complexity of that code is based on the complexity of BFS with the main difference that we keep a priority queue. For BFS we knew that the complexity was O(|V| + |E|), while Dijkstra&#8217;s algorithm has running time of O((|V| + |E|).log(|V|)). That is quite natural since the heapsort&#8217;s complexity is O(n.log(n))!</p>
<h2>Application</h2>
<p>Since the basic BFS can&#8217;t help us for weighted graphs and there are plenty of problems designed with weighted graphs obviously Dijkstra&#8217;s algorithm can be very handy. The only thing we should be aware of is the positive values of the edges.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
<li><a href="/2012/10/28/computer-algorithms-shortest-path-in-a-directed-acyclic-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Directed Acyclic Graph">Computer Algorithms: Shortest Path in a Directed Acyclic Graph </a></li>
<li><a href="/2012/10/22/computer-algorithms-bellman-ford-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Bellman-Ford Shortest Path in a Graph">Computer Algorithms: Bellman-Ford Shortest Path in a Graph </a></li>
<li><a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Breadth First Search">Computer Algorithms: Graph Breadth First Search </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Shortest Path in a Graph</title>
		<link>/2012/10/08/computer-algorithms-shortest-path-in-a-graph/</link>
		<comments>/2012/10/08/computer-algorithms-shortest-path-in-a-graph/#respond</comments>
		<pubDate>Mon, 08 Oct 2012 13:39:55 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[data structures]]></category>
		<category><![CDATA[Graphs]]></category>
		<category><![CDATA[Breadth-first search]]></category>
		<category><![CDATA[breadth-first search algorithm]]></category>
		<category><![CDATA[breadth-first search will]]></category>
		<category><![CDATA[Distance]]></category>
		<category><![CDATA[Edge disjoint shortest pair algorithm]]></category>
		<category><![CDATA[faster and more efficient algorithm]]></category>
		<category><![CDATA[graph algorithm]]></category>
		<category><![CDATA[Graph theory]]></category>
		<category><![CDATA[handy algorithm]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Network theory]]></category>
		<category><![CDATA[path]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Routing algorithms]]></category>
		<category><![CDATA[search algorithm]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[shortest path algorithm]]></category>
		<category><![CDATA[Shortest path problem]]></category>
		<category><![CDATA[Theoretical computer science]]></category>
		<category><![CDATA[Tree]]></category>
		<category><![CDATA[USD]]></category>

		<guid isPermaLink="false">/?p=3369</guid>
		<description><![CDATA[Introduction Since with graphs we can represent real-life problems it’s almost clear why we would need an efficient algorithm that calculates the shortest path between two vertices. Getting back to our example of a road map we can use such an algorithm in order to find the shortest path between two cities. This example, of &#8230; <a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Shortest Path in a Graph</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/28/computer-algorithms-shortest-path-in-a-directed-acyclic-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Directed Acyclic Graph">Computer Algorithms: Shortest Path in a Directed Acyclic Graph </a></li>
<li><a href="/2012/10/22/computer-algorithms-bellman-ford-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Bellman-Ford Shortest Path in a Graph">Computer Algorithms: Bellman-Ford Shortest Path in a Graph </a></li>
<li><a href="/2012/09/24/computer-algorithms-graph-best-first-search/" rel="bookmark" title="Computer Algorithms: Graph Best-First Search">Computer Algorithms: Graph Best-First Search </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Since with graphs we can represent real-life problems it’s almost clear why we would need an efficient algorithm that calculates the shortest path between two vertices. Getting back to our example of a road map we can use such an algorithm in order to find the shortest path between two cities. This example, of course, is very basic indeed, but it can give us a clear example of where shortest path can be applied.</p>
<p>In the other hand, we can model an enormous field of real-life problems using graphs – not only road maps. As we already know, whenever we have relations between different abstract objects we can refer an efficient graph algorithm.</p>
<p>OK, so we need a shortest path algorithm, but before we proceed with the exact algorithm first we’ll need to answer some questions and give some definitions.</p>
<h2>Overview</h2>
<p>First we need a definition of the terms distance and path between two nodes. A path is considered to be the sequence of vertices (or edges if you wish) between two vertices i and j. Of course we assume that there might be no path between any to vertices in the graph! Also we assume that this definition relates both for directed and undirected graphs. After we have the definition of a path we can proceed by defining a “distance”, which is said to be the number of edges in the path between i and j.</p>
<p><figure id="attachment_3391" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/1.-Path-and-Distance.png"><img src="/wp-content/uploads/2012/10/1.-Path-and-Distance.png" alt="Path and Distance" title="Path and Distance" width="620" height="399" class="size-full wp-image-3391" srcset="/wp-content/uploads/2012/10/1.-Path-and-Distance.png 620w, /wp-content/uploads/2012/10/1.-Path-and-Distance-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">First we need to define what&#8217;s a path and a distance between two vertices in order to continue searching for the shortest path!</figcaption></figure><span id="more-3369"></span></p>
<p>Using this terms, if there’s an edge between i and j, the path between them is [i, j], while the distance is 1. Of course, for an undirected graph (i, j) equals to (j, i) and the path [i, j] equals the path [j, i], but that isn’t true for directed graphs where the path [i, j] differs in general from [j, i].</p>
<figure id="attachment_3390" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/2.-Rule-of-the-Triangle.png"><img src="/wp-content/uploads/2012/10/2.-Rule-of-the-Triangle.png" alt="Rule of the Triangle" title="Rule of the Triangle" width="620" height="399" class="size-full wp-image-3390" srcset="/wp-content/uploads/2012/10/2.-Rule-of-the-Triangle.png 620w, /wp-content/uploads/2012/10/2.-Rule-of-the-Triangle-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Although path (shortest path) is applicable for both directed and undirectd graphs, they depend in both cases of the graph type!</figcaption></figure>
<p>Here we talk about the path between two adjacent vertices, but we can go with the more general case of a path between two vertices that aren’t adjacent. </p>
<p>Now, getting back to the road map example, there might be many paths between city A and city B. </p>
<figure id="attachment_3389" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/3.-Paths-Between-Cities.png"><img src="/wp-content/uploads/2012/10/3.-Paths-Between-Cities.png" alt="Paths Between Cities" title="Paths Between Cities" width="620" height="399" class="size-full wp-image-3389" srcset="/wp-content/uploads/2012/10/3.-Paths-Between-Cities.png 620w, /wp-content/uploads/2012/10/3.-Paths-Between-Cities-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">If we talk about paths between cities its pretty natural to talk about more than one &#8220;valid&#8221; path!</figcaption></figure>
<p>What we actually need to find is the shortest one. This can be very important, because we often want to get from A to B as quickly as possible using the shortest path.</p>
<figure id="attachment_3388" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/4.-Shortest-Path-Between-Cities.png"><img src="/wp-content/uploads/2012/10/4.-Shortest-Path-Between-Cities.png" alt="Shortest Path Between Cities" title="Shortest Path Between Cities" width="620" height="399" class="size-full wp-image-3388" srcset="/wp-content/uploads/2012/10/4.-Shortest-Path-Between-Cities.png 620w, /wp-content/uploads/2012/10/4.-Shortest-Path-Between-Cities-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">The shortest path between two vertices is the path with lower distance compared to all other paths between the same points!</figcaption></figure>
<p>So first, what is a shortest path between i and j. Well, besides the strict definition, I’ll give a simplified one that might be clearer. The shortest path between i and j is such a path, which has the lowest distance compared to all other paths between i and j. </p>
<p>In our algorithm we will use breadth-first search. Why? That is because by using BFS by starting at a given point we expand our search consecutively starting with the closest vertices.</p>
<figure id="attachment_3387" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/5.-Shortest-Path-Canvas.png"><img src="/wp-content/uploads/2012/10/5.-Shortest-Path-Canvas.png" alt="BFS: Shortest Path Canvas" title="BFS: Shortest Path Canvas" width="620" height="399" class="size-full wp-image-3387" srcset="/wp-content/uploads/2012/10/5.-Shortest-Path-Canvas.png 620w, /wp-content/uploads/2012/10/5.-Shortest-Path-Canvas-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Breadth-first search can help us find the shortest paths between a given vertex (s) and all other reachable vertices!</figcaption></figure>
<p>Is breadth-first search enough and will it give us the correct answer – the shortest path between i and j. Actually breadth-first search will gives us even more – the shortest paths to each reachable vertex from a given starting point – the staring vertex.</p>
<p>Why this is correct? Well, because of the nature of the breadth-first search algorithm. As we already know BFS uses a queue in order to store the front of the expansion. Usually as an abstraction BFS colors the vertices in white, gray and black, where the white vertices are those that aren’t visited yet, the gray are in the queue and the black vertices are already visited.</p>
<figure id="attachment_3386" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/6.-White-Gray-Black.png"><img src="/wp-content/uploads/2012/10/6.-White-Gray-Black.png" alt="White, Gray, Black" title="White, Gray, Black" width="620" height="399" class="size-full wp-image-3386" srcset="/wp-content/uploads/2012/10/6.-White-Gray-Black.png 620w, /wp-content/uploads/2012/10/6.-White-Gray-Black-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">By putting a color to visited/unvisited and currently inspected vertices we can get a clearer impression on how breadth-first search works!</figcaption></figure>
<p>However how can be sure that BFS will give us the shortest paths to each vertex? To answer this question and to be sure that BFS will work for us we must take a closer look at the queue. Clearly by starting at a given point the algorithm is correct – the distance is 0.</p>
<p>Now the second step is to put into the queue all the vertices adjacent to s (where s is the starting point). Clearly this will give us the shortest paths to all adjacent vertices of s.</p>
<p>Continuing by induction we can assume that at level k we have all the shortest paths from s to all the vertices at the level k. It is clear the path between s and the vertices at level k is k, since we assume that each edge adds 1 to the path from s to i. Now by adding all the vertices adjacent (and not visited yet) to the paths of level k we get paths with length k+1 which is again the shortest paths from s to level k+1. </p>
<figure id="attachment_3385" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/7.-Shortest-Paths.png"><img src="/wp-content/uploads/2012/10/7.-Shortest-Paths.png" alt="Shortest Paths" title="Shortest Paths" width="620" height="399" class="size-full wp-image-3385" srcset="/wp-content/uploads/2012/10/7.-Shortest-Paths.png 620w, /wp-content/uploads/2012/10/7.-Shortest-Paths-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Finding the shortest paths using BFS can be proved by induction!</figcaption></figure>
<p>Actually we can talk about a tree built out of the graph by staring at s (which is the root of the tree).</p>
<figure id="attachment_3384" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/8.-Spanning-tree.png"><img src="/wp-content/uploads/2012/10/8.-Spanning-tree.png" alt="Spanning tree" title="Spanning tree" width="620" height="399" class="size-full wp-image-3384" srcset="/wp-content/uploads/2012/10/8.-Spanning-tree.png 620w, /wp-content/uploads/2012/10/8.-Spanning-tree-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">BFS walks through the graph by constructing a virtual tree!</figcaption></figure>
<h2>Code</h2>
<p>OK, now we know that BFS will find us the shortest paths from s to all the reachable vertices from s. Here’s a simple PHP implementation, that makes use of the Standard PHP Library data structures. Of course, everyone can code and use his own implementation of lists in order to keep the information of the adjacency lists.</p>
<p>The important thing to note is that we keep an additional information in each vertex – the distance between it and s, which is initially infinite. First we go with the modification of BFS in order to find all the distances between s and the other vertices.</p>
<p>Here’s our graph:</p>
<figure id="attachment_3392" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/10/9.-Graph.png"><img src="/wp-content/uploads/2012/10/9.-Graph.png" alt="Graph" title="Graph" width="620" height="399" class="size-full wp-image-3392" srcset="/wp-content/uploads/2012/10/9.-Graph.png 620w, /wp-content/uploads/2012/10/9.-Graph-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">The graph for the example!</figcaption></figure>
<pre lang="PHP">
class vertex
{
    public $key = null;
    public $color = 'white';
    public $distance = -1;  // infinite
    
    public function __construct($key) 
    {
        $this->key = $key;
    }
}

$v0 = new vertex(0);
$v1 = new vertex(1);
$v2 = new vertex(2);
$v3 = new vertex(3);
$v4 = new vertex(4);
$v5 = new vertex(5);

$list0 = new SplDoublyLinkedList();
$list0->push($v1);
$list0->push($v3);
$list0->rewind();

$list1 = new SplDoublyLinkedList();
$list1->push($v0);
$list1->push($v2);
$list1->rewind();

$list2 = new SplDoublyLinkedList();
$list2->push($v1);
$list2->push($v3);
$list2->push($v4);
$list2->rewind();

$list3 = new SplDoublyLinkedList();
$list3->push($v1);
$list3->push($v2);
$list3->rewind();

$list4 = new SplDoublyLinkedList();
$list4->push($v2);
$list4->push($v5);
$list4->rewind();

$list5 = new SplDoublyLinkedList();
$list5->push($v4);
$list5->rewind();

$adjacencyList = array(
    $list0,
    $list1,
    $list2,
    $list3,
    $list4,
    $list5,
);

function calcDistances(vertex $start, &$adjLists)
{
    // define an empty queue
    $q = array();
    
    // push the starting vertex into the queue
    array_push($q, $start);
    
    // color it gray
    $start->color = 'gray';
    
    // mark the distance to it 0
    $start->distance = 0;
    
    while ($q) {
        // 1. pop from the queue
        $t = array_pop($q);
        
        // 2. foreach poped item find it's adjacent white vertices
        $l = $adjLists[$t->key];
        while ($l->valid()) {
            // 3. mark them gray, increment their length with one from their parent
            if ($l->current()->color == 'white') {
                $l->current()->color = 'gray';
                $l->current()->distance = $t->distance + 1;
                // 4. push them to the queue
                array_push($q, $l->current());
            }
            
            $l->next();
        }
    }
}

calcDistances($v0, $adjacencyList);

print_r($adjacencyList);
</pre>
<p>Now we can modify the algorithm even more and we add the path property of each vertex. Now each vertex will keep the path from s.</p>
<pre lang="PHP">
class vertex
{
    public $key         = null;
    public $color       = 'white';
    public $distance    = -1;  // infinite
    public $path        = null;
    
    public function __construct($key) 
    {
        $this->key  = $key;
    }
}

$v0 = new vertex(0);
$v1 = new vertex(1);
$v2 = new vertex(2);
$v3 = new vertex(3);
$v4 = new vertex(4);
$v5 = new vertex(5);

$list0 = new SplDoublyLinkedList();
$list0->push($v1);
$list0->push($v3);
$list0->rewind();

$list1 = new SplDoublyLinkedList();
$list1->push($v0);
$list1->push($v2);
$list1->rewind();

$list2 = new SplDoublyLinkedList();
$list2->push($v1);
$list2->push($v3);
$list2->push($v4);
$list2->rewind();

$list3 = new SplDoublyLinkedList();
$list3->push($v1);
$list3->push($v2);
$list3->rewind();

$list4 = new SplDoublyLinkedList();
$list4->push($v2);
$list4->push($v5);
$list4->rewind();

$list5 = new SplDoublyLinkedList();
$list5->push($v4);
$list5->rewind();

$adjacencyList = array(
    $list0,
    $list1,
    $list2,
    $list3,
    $list4,
    $list5,
);

function calcShortestPaths(vertex $start, &$adjLists)
{
    // define an empty queue
    $q = array();
    
    // push the starting vertex into the queue
    array_push($q, $start);
    
    // color it gray
    $start->color = 'gray';
    
    // mark the distance to it 0
    $start->distance = 0;
    
    // the path to the starting vertex
    $start->path = new SplDoublyLinkedList();
    $start->path->push($start->key);
    
    while ($q) {
        // 1. pop from the queue
        $t = array_pop($q);
        
        // 2. foreach poped item find it's adjacent white vertices
        $l = $adjLists[$t->key];
        while ($l->valid()) {
            // 3. mark them gray, increment their length with one from their parent
            if ($l->current()->color == 'white') {
                $l->current()->color = 'gray';
                $l->current()->distance = $t->distance + 1;
                $l->current()->path = clone $t->path;
                $l->current()->path->push($l->current()->key);
                
                // 4. push them to the queue
                array_push($q, $l->current());
            }
            
            $l->next();
        }
    }
}

calcShortestPaths($v0, $adjacencyList);

print_r($adjacencyList);
</pre>
<h2>Complexity</h2>
<p>Clearly the complexity of enqueue and dequeue is O(V), while searching for adjacent vertices is O(E), thus the complexity of this algorithm is O(V + E)!</p>
<h2>Application</h2>
<p>Finding the shortest path between two nodes is obviousely a very handy algorithm. Applied almost everywhere graphs exists this algorithm is widely used. However there&#8217;s one very reasonable question. We&#8217;re searching for the shortest path between two vertices and we end with the shortest paths between a starting node an all other vertices? Why we need this &#8220;useless&#8221; information? Acutally the question should be: is there a faster and more efficient algorithm compared to this one. Well, we&#8217;ll see that!</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/28/computer-algorithms-shortest-path-in-a-directed-acyclic-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Directed Acyclic Graph">Computer Algorithms: Shortest Path in a Directed Acyclic Graph </a></li>
<li><a href="/2012/10/22/computer-algorithms-bellman-ford-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Bellman-Ford Shortest Path in a Graph">Computer Algorithms: Bellman-Ford Shortest Path in a Graph </a></li>
<li><a href="/2012/09/24/computer-algorithms-graph-best-first-search/" rel="bookmark" title="Computer Algorithms: Graph Best-First Search">Computer Algorithms: Graph Best-First Search </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/10/08/computer-algorithms-shortest-path-in-a-graph/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Graph Best-First Search</title>
		<link>/2012/09/24/computer-algorithms-graph-best-first-search/</link>
		<comments>/2012/09/24/computer-algorithms-graph-best-first-search/#comments</comments>
		<pubDate>Mon, 24 Sep 2012 10:44:53 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[data structures]]></category>
		<category><![CDATA[Adjacency matrix]]></category>
		<category><![CDATA[Algebraic graph theory]]></category>
		<category><![CDATA[Breadth-first search]]></category>
		<category><![CDATA[Depth-first search]]></category>
		<category><![CDATA[Graph]]></category>
		<category><![CDATA[Graph theory]]></category>
		<category><![CDATA[graph traversal algorithms]]></category>
		<category><![CDATA[Hopcroft–Karp algorithm]]></category>
		<category><![CDATA[Matching]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Path decomposition]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[possible solution]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[two algorithms]]></category>
		<category><![CDATA[typical greedy algorithm]]></category>
		<category><![CDATA[USD]]></category>

		<guid isPermaLink="false">/?p=3347</guid>
		<description><![CDATA[Introduction So far we know how to implement graph depth-first and breadth-first search. These two approaches are crucial in order to understand graph traversal algorithms. However they are just explaining how we can walk through in breadth or depth and sometimes this isn&#8217;t enough for an efficient solution of graph traversal. In the examples so &#8230; <a href="/2012/09/24/computer-algorithms-graph-best-first-search/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Graph Best-First Search</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/09/17/computer-algorithms-graph-depth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Depth-First Search">Computer Algorithms: Graph Depth-First Search </a></li>
<li><a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Breadth First Search">Computer Algorithms: Graph Breadth First Search </a></li>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>So far we know how to implement graph <a href="/2012/09/17/computer-algorithms-graph-depth-first-search/" title="Computer Algorithms: Graph Depth-First Search">depth-first</a> and <a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" title="Computer Algorithms: Graph Breadth First Search">breadth-first</a> search. These two approaches are crucial in order to understand graph traversal algorithms. However they are just explaining how we can walk through in breadth or depth and sometimes this isn&#8217;t enough for an efficient solution of graph traversal.</p>
<p>In the examples so far we had an undirected, unweighted graph and we were using adjacency matrices to represent the graphs. By <a href="/2012/08/31/computer-algorithms-graphs-and-their-representation/" title="Computer Algorithms: Graphs and their Representation">using adjacency matrices</a> we store <strong>1</strong> in the A[i][j] if there’s an edge between vertex i and vertex j. Otherwise we put a <strong>0</strong>. However the value of <strong>1</strong> gives us only the information that we have an edge between two vertices, which is not always enough when designing graphs.</p>
<p>Indeed graphs can be weighted. Sometimes the path between two vertices can have a value. Thinking of a road map we know that distances between cities are represented in miles or kilometers. Thus often representing a road map as a graph, we don’t put just 1 between city A and city B, to say that there is a path between them, but also we put some meaningful information – let’s say the distance in miles between A and B. </p>
<p>Note that this value can be the distance in miles, but it can be something else, like the time in hours we’ve to walk between those two cities. In general this value is a function of A and B. So if we keep the distance between A and B we can say this function is F(A, B) = X, or distance(A, B) = X miles.</p>
<p>Of course in this particular example F(A, B) = F(B, A), but this isn’t always true in practice. We can have a directed graph where F(A, B) != F(B, A).</p>
<p>Here I talk about distance between two cities and it is the edge that brings some additional information. However sometimes we have to store the value of the vertices. Let&#8217;s say I&#8217;m playing a game (like chess) and each move brings me some additional benefit. So each move (vertex) can be evaluated with some particular value. Thus sometimes we don&#8217;t have a function of and edge like F(A, B), but function of the vertices, like F(A) and F(B).</p>
<p>In breadth-first search and depth-first search we just pick up a vertex and we consecutively walk through all its successors that haven’t been visited yet.</p>
<figure id="attachment_3357" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/1.-Unweithed-Graph-Walkthrough.png"><img src="/wp-content/uploads/2012/09/1.-Unweithed-Graph-Walkthrough.png" alt="Walk Through an Unweithed Graph" title="Unweithed Graph Walkthrough" width="620" height="399" class="size-full wp-image-3357" srcset="/wp-content/uploads/2012/09/1.-Unweithed-Graph-Walkthrough.png 620w, /wp-content/uploads/2012/09/1.-Unweithed-Graph-Walkthrough-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">In order to walk through an unweithed graph using DFS, we chose consecutively each successor of node i!</figcaption></figure>
<p>So in DFS in particular we started from left to right in the array above. So the first node that has to be explored is vertex “1”.</p>
<pre lang="PHP">
0: [0, 1, 0, 0, 1, 1]
</pre>
<p>However sometimes, as I said above, we have weighted graphs, so the question is – is there any problem, regarding to the algorithm speed, if we go consecutively through all successors. The answer in general is yes, so we must modify a bit our code in order to continue not with the first but with the best matching successor. By best-matching we mean that the successor should match some criteria like – minimal or maximal value.<span id="more-3347"></span></p>
<h2>Overview</h2>
<p>In the following example we see that some of the successors of vertex 0 are very far from it, while others are closer. Thus 4 has the value of 5, while node 1’s value is 2 and 5 is 1.</p>
<figure id="attachment_3359" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/2.-BFS-and-Weighted-Graph.png"><img src="/wp-content/uploads/2012/09/2.-BFS-and-Weighted-Graph.png" alt="DFS and Weighted Graph" title="DFS and Weighted Graph" width="620" height="399" class="size-full wp-image-3359" srcset="/wp-content/uploads/2012/09/2.-BFS-and-Weighted-Graph.png 620w, /wp-content/uploads/2012/09/2.-BFS-and-Weighted-Graph-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Weithed graph brings us more information about the successors of a given vertex. Thus we have to chose carefully which one to get first in our path exploration!</figcaption></figure>
<pre lang="PHP">
0: [0, 2, 0, 0, 5, 1]
</pre>
<p>In this case if we’re searching for the shortest path between 1 and 3, although 1 and 4 are the first two successors in the adjacency matrix of the &#8220;start&#8221; vertex, we don&#8217;t choose them since there’s a better solution – going through node 5.</p>
<figure id="attachment_3360" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/3.-Best-First-Search.png"><img src="/wp-content/uploads/2012/09/3.-Best-First-Search.png" alt="Best-First Search" title="Best-First Search" width="620" height="399" class="size-full wp-image-3360" srcset="/wp-content/uploads/2012/09/3.-Best-First-Search.png 620w, /wp-content/uploads/2012/09/3.-Best-First-Search-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">In best-first search we continue the path to the target through the best-matching successor!</figcaption></figure>
<h3>Problems</h3>
<p>The question is – are we sure that by choosing node 5, we’ll find the best path? Even more! Is there a path through node 5? As we see on the image below both cases are possible.</p>
<figure id="attachment_3361" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/4.-BFS-problems.png"><img src="/wp-content/uploads/2012/09/4.-BFS-problems.png" alt="BFS problems" title="BFS problems" width="620" height="399" class="size-full wp-image-3361" srcset="/wp-content/uploads/2012/09/4.-BFS-problems.png 620w, /wp-content/uploads/2012/09/4.-BFS-problems-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Somtimes best-first search doesn&#8217;t find the &#8220;best&#8221; (shortest/longest/cheapest) path to the target!</figcaption></figure>
<p>Practically best-first search is identical with depth-first search, with the main difference that we choose the best-matching successor instead of choosing the first matching successor. So we’re sure that we’re going through all the successors but in some particular order, different from DFS. Thus we know that if there’s a path we’ll find it.</p>
<p>However even if we find the path between A and B, we can’t be sure that there is not a better path. We only know that this path is the best so far. </p>
<p>Another question is – how can we find the best matching successor effectively. Well if we’re looking for the minimal or maximal value one possible solution is to sort the array of successors.</p>
<figure id="attachment_3363" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/5.-Using-Priority-Queues.png"><img src="/wp-content/uploads/2012/09/5.-Using-Priority-Queues.png" alt="Using Priority Queues" title="Using Priority Queues" width="620" height="412" class="size-full wp-image-3363" srcset="/wp-content/uploads/2012/09/5.-Using-Priority-Queues.png 620w, /wp-content/uploads/2012/09/5.-Using-Priority-Queues-300x199.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">The difference between depth-first and best-first is that we change the order of chosing the next successor!</figcaption></figure>
<pre lang="PHP">
0: [0 => 0, 1 => 2, 2 => 0, 3 => 0, 4 => 5, 5 => 1]
// sorted by value
0: [5 => 1, 1 => 2, 4 => 5, 0 => 0, 2 => 0, 3 => 1]
</pre>
<p>Another good approach will be to use priority queues or heaps.</p>
<p>Thus on every step we’ll get the best matching successor.</p>
<h2>Code</h2>
<p>In general best-first search uses the ground of depth-first search, so its implementation isn&#8217;t more difficult! The following PHP code snippet shows the very small difference between these two algorithms.</p>
<pre lang="PHP">
class Graph 
{
    protected $_len = 0;
    protected $_g = array();
    protected $_visited = array();
    
    public function __construct()
    {
        $this->_g = array(
            array(0, 2, 0, 0, 5, 1),
            array(1, 0, 3, 0, 0, 0),
            array(0, 2, 0, 8, 0, 0),
            array(0, 0, 3, 0, 5, 0),
            array(1, 0, 0, 8, 0, 1),
            array(1, 0, 0, 0, 5, 0),
        );
        
        $this->_len = count($this->_g);
        
        $this->_initVisited();
    }
    
    protected function _initVisited()
    {
        for ($i = 0; $i < $this->_len; $i++) {
            $this->_visited[$i] = 0;
        }
    }
    
    public function bestFirst($vertex)
    {
        $this->_visited[$vertex] = 1;
    
        echo $vertex . "\n";
        
        asort($this->_g[$vertex]);
        
        foreach ($this->_g[$vertex] as $key => $v) {
            if ($v > 0 && !$this->_visited[$key]) {
                $this->bestFirst($key);
            }
        }
    }
}

$g = new Graph();
// 2 1 0 5 4 3
$g->bestFirst(2);
</pre>
<h2>Application</h2>
<p>Best-first search is a typical greedy algorithm. In its principles lies the main greedy approach of chosing the best possible solution so far. It is important to note that depth-first search and breadth-first search are the very basic graph walk through approaches, but they can be also widely extended in order to solve more complex problems.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/09/17/computer-algorithms-graph-depth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Depth-First Search">Computer Algorithms: Graph Depth-First Search </a></li>
<li><a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Breadth First Search">Computer Algorithms: Graph Breadth First Search </a></li>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/09/24/computer-algorithms-graph-best-first-search/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Graph Depth-First Search</title>
		<link>/2012/09/17/computer-algorithms-graph-depth-first-search/</link>
		<comments>/2012/09/17/computer-algorithms-graph-depth-first-search/#comments</comments>
		<pubDate>Mon, 17 Sep 2012 10:52:59 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[data structures]]></category>
		<category><![CDATA[Breadth-first search]]></category>
		<category><![CDATA[Combinatorics]]></category>
		<category><![CDATA[Connectivity]]></category>
		<category><![CDATA[Depth-first search]]></category>
		<category><![CDATA[Graph theory]]></category>
		<category><![CDATA[graph-walk algorithm]]></category>
		<category><![CDATA[In-place algorithm]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[specific algorithms]]></category>
		<category><![CDATA[two main algorithms]]></category>
		<category><![CDATA[USD]]></category>

		<guid isPermaLink="false">/?p=3340</guid>
		<description><![CDATA[Introduction Along with breadth-first search, depth-first search is one of the two main methods to walk through a graph. This approach though is different. Breadth-first search (BFS) looks pretty much like starting from a vertex and expanding the searching process level by level. This means that first we get some information of all the successors &#8230; <a href="/2012/09/17/computer-algorithms-graph-depth-first-search/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Graph Depth-First Search</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/09/24/computer-algorithms-graph-best-first-search/" rel="bookmark" title="Computer Algorithms: Graph Best-First Search">Computer Algorithms: Graph Best-First Search </a></li>
<li><a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Breadth First Search">Computer Algorithms: Graph Breadth First Search </a></li>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Along with <a title="Computer Algorithms: Graph Breadth First Search" href="/2012/09/10/computer-algorithms-graph-breadth-first-search/">breadth-first search</a>, depth-first search is one of the two main methods to walk through a graph. This approach though is different. Breadth-first search (BFS) looks pretty much like starting from a vertex and expanding the searching process level by level. This means that first we get some information of all the successors of the given node and then we go further with the next level. In other words BFS is like a wave. Depth-first search is based on a different approach, which can be very useful in some specific algorithms.</p>
<figure id="attachment_3348" style="width: 621px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/1.-DFS-vs.-BFS.png"><img class="size-full wp-image-3348" title="DFS vs. BFS" src="/wp-content/uploads/2012/09/1.-DFS-vs.-BFS.png" alt="DFS vs. BFS" width="621" height="351" srcset="/wp-content/uploads/2012/09/1.-DFS-vs.-BFS.png 621w, /wp-content/uploads/2012/09/1.-DFS-vs.-BFS-300x169.png 300w" sizes="(max-width: 621px) 100vw, 621px" /></a><figcaption class="wp-caption-text">Depth-first and breadth-first search are the two main ways to explore a graph!</figcaption></figure>
<p>Both methods can be useful in solving different tasks.<span id="more-3340"></span></p>
<h2>Overview</h2>
<p>Depth-first search is an algorithm that by given starting and target node, finds a path between them. We can use DFS also to walk through all the vertices of a graph, in case the graph is connected.</p>
<figure id="attachment_3350" style="width: 621px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/2.-DFS-explained.png"><img class="size-full wp-image-3350" title="DFS explained" src="/wp-content/uploads/2012/09/2.-DFS-explained.png" alt="DFS explained" width="621" height="351" srcset="/wp-content/uploads/2012/09/2.-DFS-explained.png 621w, /wp-content/uploads/2012/09/2.-DFS-explained-300x169.png 300w" sizes="(max-width: 621px) 100vw, 621px" /></a><figcaption class="wp-caption-text">The algorithm frist goes in depth and then backtracks to all unvisited successors!</figcaption></figure>
<p>The whole idea of this algorithm is to go as far as possible from the given starting node searching for the target. In case we get to a node that has no successors, we get back (typically this is done recursively) and we continue with the last vertex that isn’t visited yet.</p>
<p>So basically we have 3 steps:</p>
<ol>
<li>Pick up a vertex that isn&#8217;t visited yet and mark it visited;</li>
<li>Go to its first non-visited successor and mark it visited;</li>
<li>If all the successors of the vertex are already visited or it doesn&#8217;t have successors &#8211; go back to its parent;</li>
</ol>
<h2>Code</h2>
<p>The following <a href="/category/php/" title="PHP on Stoimen.com">PHP</a> code implements the depth-first search. The key point is the recursion in the method depthFirst.</p>
<pre lang="PHP">
class Graph 
{
    protected $_len = 0;
    protected $_g = array();
    protected $_visited = array();
    
    public function __construct()
    {
        $this->_g = array(
            array(0, 1, 1, 0, 0, 0),
            array(1, 0, 0, 1, 0, 0),
            array(1, 0, 0, 1, 1, 1),
            array(0, 1, 1, 0, 1, 0),
            array(0, 0, 1, 1, 0, 1),
            array(0, 0, 1, 0, 1, 0),
        );
        
        $this->_len = count($this->_g);
        
        $this->_initVisited();
    }
    
    protected function _initVisited()
    {
        for ($i = 0; $i < $this->_len; $i++) {
            $this->_visited[$i] = 0;
        }
    }
    
    public function depthFirst($vertex)
    {
        $this->_visited[$vertex] = 1;
    
        echo $vertex . "\n";
        
        for ($i = 0; $i < $this->_len; $i++) {
            if ($this->_g[$vertex][$i] == 1 && !$this->_visited[$i]) {
                $this->depthFirst($i);
            }
        }
    }
}

$g = new Graph();
// 2 0 1 3 4 5
$g->depthFirst(2);
</pre>
<h2>Complexity</h2>
<p>By using an adjacency matrix we need n<sup>2</sup> space for a graph with <strong>n</strong> vertices. We also use an additional array to mark visited vertices, which requires additional space of <strong>n</strong>! Thus the space complexity is O(n<sup>2</sup>).</p>
<p>When it comes to time complexity since we have a recursion and we try visiting all the vertices on each step, the worst-case time is yet again O(n<sup>2</sup>)!</p>
<h2>Application</h2>
<p>This graph-walk algorithm can be very useful when solving some specific tasks like finding the shortest/longest paths in a graph. Although <a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" title="Computer Algorithms: Graph Breadth First Search">BFS</a> and DFS aren&#8217;t the only methods of walking through a graph, they are considered the two main algorithms of that kind. This is important in order to solve graph-based problems.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/09/24/computer-algorithms-graph-best-first-search/" rel="bookmark" title="Computer Algorithms: Graph Best-First Search">Computer Algorithms: Graph Best-First Search </a></li>
<li><a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Breadth First Search">Computer Algorithms: Graph Breadth First Search </a></li>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/09/17/computer-algorithms-graph-depth-first-search/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Graph Breadth First Search</title>
		<link>/2012/09/10/computer-algorithms-graph-breadth-first-search/</link>
		<comments>/2012/09/10/computer-algorithms-graph-breadth-first-search/#comments</comments>
		<pubDate>Sun, 09 Sep 2012 21:52:49 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[data structures]]></category>
		<category><![CDATA[Breadth-first search]]></category>
		<category><![CDATA[Connected component]]></category>
		<category><![CDATA[Depth-first search]]></category>
		<category><![CDATA[Dijkstra's algorithm]]></category>
		<category><![CDATA[Graph]]></category>
		<category><![CDATA[graph algorithms]]></category>
		<category><![CDATA[Graph theory]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[search start]]></category>
		<category><![CDATA[search walks]]></category>
		<category><![CDATA[Theoretical computer science]]></category>

		<guid isPermaLink="false">/?p=3338</guid>
		<description><![CDATA[Introduction Since we already know how to represent graphs, we can go further for some very simple approaches of walking through them. Passing by all the vertices of a graph is a fundamental technique for most of the graph algorithms, such as finding shortest/longest paths, etc. First thing to note is that graphs are not &#8230; <a href="/2012/09/10/computer-algorithms-graph-breadth-first-search/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Graph Breadth First Search</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/09/17/computer-algorithms-graph-depth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Depth-First Search">Computer Algorithms: Graph Depth-First Search </a></li>
<li><a href="/2012/09/24/computer-algorithms-graph-best-first-search/" rel="bookmark" title="Computer Algorithms: Graph Best-First Search">Computer Algorithms: Graph Best-First Search </a></li>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Since we already know <a href="/2012/08/31/computer-algorithms-graphs-and-their-representation/" title="Computer Algorithms: Graphs and their Representation">how to represent graphs</a>, we can go further for some very simple approaches of walking through them. Passing by all the vertices of a graph is a fundamental technique for most of the graph algorithms, such as finding shortest/longest paths, etc.</p>
<p>First thing to note is that graphs are not trees, in most of the cases, so walking through them can&#8217;t start from a root, as we do with trees. What we must do first is to decide from where to start – in other words &#8211; choosing a starting vertex. </p>
<figure id="attachment_3343" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/1.-BFS-Choosing-a-Starting-Point.png"><img src="/wp-content/uploads/2012/09/1.-BFS-Choosing-a-Starting-Point.png" alt="BFS Choosing a Starting Point" title="BFS Choosing a Starting Point" width="620" height="399" class="size-full wp-image-3343" srcset="/wp-content/uploads/2012/09/1.-BFS-Choosing-a-Starting-Point.png 620w, /wp-content/uploads/2012/09/1.-BFS-Choosing-a-Starting-Point-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">It&#8217;s clear that depending on the starting point we can get different passes through the graph. Thus choosing a starting point can be very important for our algorithm!</figcaption></figure>
<p>After that we need to know how to proceed. There are two approaches mostly known as “breadth first” and “depth first” search. While depth first search start from a vertex and goes as far as possible, then walks back and passes through vertices that haven’t been visited yet, breath first search is an approach of passing through all the neighbors of the node first, and then go to the next level.<br />
<span id="more-3338"></span></p>
<h2>Overview</h2>
<p>We can thing of breadth first search as a “wave” walk through the graph. In other words we go level by level, as shown on the picture below.</p>
<figure id="attachment_3344" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/2.-BFS-Wave.png"><img src="/wp-content/uploads/2012/09/2.-BFS-Wave.png" alt="BFS Wave" title="BFS Wave" width="620" height="399" class="size-full wp-image-3344" srcset="/wp-content/uploads/2012/09/2.-BFS-Wave.png 620w, /wp-content/uploads/2012/09/2.-BFS-Wave-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">For this very specific graph on the picture we can see how breadth first search walks through the graph level by level!</figcaption></figure>
<p>Initially we mark all vertices as unvisited. A common approach is to create an empty queue where we put the vertices level by level, starting with the initial vertex.</p>
<figure id="attachment_3342" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/09/3.-BFS-Using-a-Queue.png"><img src="/wp-content/uploads/2012/09/3.-BFS-Using-a-Queue.png" alt="BFS Using a Queue" title="BFS Using a Queue" width="620" height="399" class="size-full wp-image-3342" srcset="/wp-content/uploads/2012/09/3.-BFS-Using-a-Queue.png 620w, /wp-content/uploads/2012/09/3.-BFS-Using-a-Queue-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Using a queue is a typical approach for breadth first search! However this requires more space!</figcaption></figure>
<h2>Code</h2>
<p>This simple approach is fairly easy to implement. Here’s the <a href="/category/php/" title="PHP on Stoimen.com">PHP</a> implementation in few lines of code.</p>
<pre lang="PHP">
<?php

$g = array(
    0 => array(0, 1, 1, 0, 0, 0),
    1 => array(1, 0, 0, 1, 0, 0),
    2 => array(1, 0, 0, 1, 0, 0),
    3 => array(0, 1, 1, 0, 1, 0),
    4 => array(0, 0, 0, 1, 0, 1),
    5 => array(0, 0, 0, 0, 1, 0),
);

function init(&$visited, &$graph) 
{
    foreach ($graph as $key => $vertex) {
        $visited[$key] = 0;
    }
}

function breadth_first(&$graph, $start, $visited)
{
    // create an empty queue
    $q = array();
    
    // initially enqueue only the starting vertex
    array_push($q, $start);
    $visited[$start] = 1;
    echo $start . "\n";
    
    while (count($q)) {
        $t = array_shift($q);
        
        foreach ($graph[$t] as $key => $vertex) {
            if (!$visited[$key] && $vertex == 1) {
                $visited[$key] = 1;
                array_push($q, $key);
                echo $key . "\t";
            }
        }
        echo "\n";
    }
}

$visited = array();
init($visited, $g);
breadth_first($g, 2, $visited);
</pre>
<h2>Complexity</h2>
<p>The complexity of this algorithm clearly is O(n<sup>2</sup>).</p>
<h2>Application</h2>
<p>As I said breadth first and depth first searches are used in many practical cases, as finding shortest/minimal paths etc. That is why understanding these basic principles of walking through a graph is crucial for other, more complex, graph algorithms.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/09/17/computer-algorithms-graph-depth-first-search/" rel="bookmark" title="Computer Algorithms: Graph Depth-First Search">Computer Algorithms: Graph Depth-First Search </a></li>
<li><a href="/2012/09/24/computer-algorithms-graph-best-first-search/" rel="bookmark" title="Computer Algorithms: Graph Best-First Search">Computer Algorithms: Graph Best-First Search </a></li>
<li><a href="/2012/10/15/computer-algorithms-dijkstra-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Dijkstra Shortest Path in a Graph">Computer Algorithms: Dijkstra Shortest Path in a Graph </a></li>
<li><a href="/2012/10/08/computer-algorithms-shortest-path-in-a-graph/" rel="bookmark" title="Computer Algorithms: Shortest Path in a Graph">Computer Algorithms: Shortest Path in a Graph </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/09/10/computer-algorithms-graph-breadth-first-search/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<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>
		<item>
		<title>Computer Algorithms: Rabin-Karp String Searching</title>
		<link>/2012/04/02/computer-algorithms-rabin-karp-string-searching/</link>
		<comments>/2012/04/02/computer-algorithms-rabin-karp-string-searching/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 19:48:15 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[ASCII]]></category>
		<category><![CDATA[basic sub-string matching algorithm]]></category>
		<category><![CDATA[Boyer–Moore string search algorithm]]></category>
		<category><![CDATA[Complexity The Rabin-Karp algorithm]]></category>
		<category><![CDATA[Cryptographic hash function]]></category>
		<category><![CDATA[Cryptography]]></category>
		<category><![CDATA[Hash function]]></category>
		<category><![CDATA[Hash table]]></category>
		<category><![CDATA[Hashing]]></category>
		<category><![CDATA[Michael O. Rabin]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Rabin-Karp algorithm]]></category>
		<category><![CDATA[Rabin-Karp string search algorithm]]></category>
		<category><![CDATA[Richard M. Karp]]></category>
		<category><![CDATA[Rolling hash]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[string matching algorithms]]></category>
		<category><![CDATA[String searching algorithm]]></category>
		<category><![CDATA[string searching algorithms]]></category>
		<category><![CDATA[sub-string matching algorithms]]></category>
		<category><![CDATA[This algorithm]]></category>

		<guid isPermaLink="false">/?p=2991</guid>
		<description><![CDATA[Introduction Brute force string matching is the a very basic sub-string matching algorithm, but it’s good for some reasons. For example it doesn’t require preprocessing of the text or the pattern. The problem is that it’s very slow. That is why in many cases brute force matching can’t be very useful. For pattern matching we &#8230; <a href="/2012/04/02/computer-algorithms-rabin-karp-string-searching/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Rabin-Karp 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/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/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><a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" title="Computer Algorithms: Brute Force String Searching">Brute force string matching</a> is the a very basic sub-string matching algorithm, but it’s good for some reasons. For example it doesn’t require preprocessing of the text or the pattern. The problem is that it’s very slow. That is why in many cases brute force matching can’t be very useful. For pattern matching we need something faster, but to understand other sub-string matching algorithms let’s take a look once again on brute force matching. </p>
<p>In brute force sub-string matching we checked every single character from the text with the first character of the pattern. Once we have a match between them we shift the comparison between the second character of the pattern with the next character of the text, as shown on the picture below.</p>
<p><figure id="attachment_3002" style="width: 618px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Rabin-Karp-Brute-Froce-Principles.png"><img src="/wp-content/uploads/2012/04/Rabin-Karp-Brute-Froce-Principles.png" alt="Brute Froce Principles" title="Brute Froce Principles" width="618" height="242" class="size-full wp-image-3002" srcset="/wp-content/uploads/2012/04/Rabin-Karp-Brute-Froce-Principles.png 618w, /wp-content/uploads/2012/04/Rabin-Karp-Brute-Froce-Principles-300x117.png 300w" sizes="(max-width: 618px) 100vw, 618px" /></a><figcaption class="wp-caption-text">Brute force string matching is slow because it compares every single character from the pattern and the text!</figcaption></figure><span id="more-2991"></span></p>
<p>This algorithm is slow for mainly two reasons. First we have to check every single character from the text. On the other hand even if we find a match between a text character and the first character of the pattern we continue to check step by step (character by character) every single symbol of the pattern in order to find whether it is in the text. So is there any other approach to find whether the text contains the pattern?</p>
<p>In fact there is a “faster” approach. In this case in order to avoid the comparison between the pattern and the text character by character, we’ll try to compare them at once, so we need a good hash function. With its help we can hash the pattern and check against hashed sub-strings of the text. We must be sure that the hash function is returning “small” hash codes for larger sub-strings. Another problem is that for larger patterns we can’t expect to have short hashes. But besides this the approach should be quite effective compared to the brute force string matching. </p>
<p>That approach is known as Rabin-Karp algorithm.</p>
<h2>Overview</h2>
<p><a href="http://en.wikipedia.org/wiki/Michael_O._Rabin" title="Michael O. Rabin" target="_blank">Michael O. Rabin</a> and <a href="http://en.wikipedia.org/wiki/Richard_M._Karp" title="Richard M. Karp" target="_blank">Richard M. Karp</a> came up with the idea of hashing the pattern and to check it against a hashed sub-string from the text in 1987. In general the idea seems quite simple, the only thing is that we need a hash function that gives different hashes for different sub-strings. Such hash function, for instance, may use the ASCII codes for every character, but we must be careful for multi-lingual support.</p>
<figure id="attachment_3003" style="width: 621px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Rabin-Karp-Basic-Principles.png"><img src="/wp-content/uploads/2012/04/Rabin-Karp-Basic-Principles.png" alt="Rabin-Karp Basic Principles" title="Rabin-Karp Basic Principles" width="621" height="299" class="size-full wp-image-3003" srcset="/wp-content/uploads/2012/04/Rabin-Karp-Basic-Principles.png 621w, /wp-content/uploads/2012/04/Rabin-Karp-Basic-Principles-300x144.png 300w" sizes="(max-width: 621px) 100vw, 621px" /></a><figcaption class="wp-caption-text">Rabin-Karp hashes the pattern and the sub-string in order to compare them quickly!</figcaption></figure>
<p>The hash function may vary depending on many things, so it may consist of ASCII char to number converting, but it can be also anything else. The only thing we need is to convert a string (pattern) into some hash that is faster to compare. Let’s say we have the string “hello world”, and let’s assume that its hash is hash(‘hello world’) = 12345. So if hash(‘he’) = 1 we can say that the pattern “he” is contained in the text “hello world”. Thus on every step we take from the text a sub-string with the length of m, where m is the pattern length. Thus we hash this sub-string and we can directly compare it to the hashed pattern, as on the picture above.</p>
<h2>Implementation</h2>
<p>So far we saw some diagrams explaining the Rabin-Karp algorithm, but let’s take a look on its implementation. Here in this very basic example where a simple hash table is used in order to convert the characters into integers. The code is PHP and it&#8217;s used only to illustrate the principles of this algorithm.</p>
<pre lang="PHP">
function hash_string($str, $len)
{
	$hash = '';
 
	$hash_table = array(
		'h' => 1,
		'e' => 2,
		'l' => 3,
		'o' => 4,
		'w' => 5,
		'r' => 6,
		'd' => 7,
	);
 
	for ($i = 0; $i < $len; $i++) {
		$hash .= $hash_table[$str{$i}];
	}
 
	return (int)$hash;
}
 
function rabin_karp($text, $pattern)
{
	$n = strlen($text);
	$m = strlen($pattern);
 
	$text_hash = hash_string(substr($text, 0, $m), $m);
	$pattern_hash = hash_string($pattern, $m);
 
	for ($i = 0; $i < $n-$m+1; $i++) {
		if ($text_hash == $pattern_hash) {
			return $i;
		}
 
		$text_hash = hash_string(substr($text, $i, $m), $m);
	}
 
	return -1;
}
 
// 2
echo rabin_karp('hello world', 'ello');
</pre>
<h3>Multiple Pattern Match</h3>
<p>It’s great to say that the Rabin-Karp algorithm is great for multiple pattern match. Indeed its nature is supposed to support such functionality, which is its advantage in compare to other string searching algorithms.</p>
<h2>Complexity</h2>
<p>The Rabin-Karp algorithm has the complexity of O(nm) where <strong>n</strong>, of course, is the length of the text, while <strong>m</strong> is the length of the pattern. So where it is compared to brute-force matching? Well, brute force matching complexity is O(nm), so as it seems there’s no much gain in performance. However it’s considered that Rabin-Karp’s complexity is O(n+m) in practice, and that makes it a bit faster, as shown on the chart below.</p>
<figure id="attachment_3001" style="width: 600px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Rabin-Karp-Complexity.png"><img src="/wp-content/uploads/2012/04/Rabin-Karp-Complexity.png" alt="Rabin-Karp Complexity" title="Rabin-Karp Complexity" width="600" height="371" class="size-full wp-image-3001" srcset="/wp-content/uploads/2012/04/Rabin-Karp-Complexity.png 600w, /wp-content/uploads/2012/04/Rabin-Karp-Complexity-300x185.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a><figcaption class="wp-caption-text">Rabin-Karp&#039;s complexity is O(nm), but in practice it&#039;s O(n+m)!</figcaption></figure>
<p>Note that the Rabin-Karp algorithm also needs O(m) preprocessing time.</p>
<h2>Application</h2>
<p>As we saw Rabin-Karp is not so faster than brute force matching. So where we should use it?</p>
<h3>3 Reasons Why Rabin-Karp is Cool</h3>
<p>1. Good for plagiarism, because it can deal with multiple pattern matching!<br />
<figure id="attachment_3000" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/04/Application-of-Rabin-Karp.png"><img src="/wp-content/uploads/2012/04/Application-of-Rabin-Karp.png" alt="Application of Rabin-Karp" title="Application of Rabin-Karp" width="620" height="399" class="size-full wp-image-3000" srcset="/wp-content/uploads/2012/04/Application-of-Rabin-Karp.png 620w, /wp-content/uploads/2012/04/Application-of-Rabin-Karp-300x193.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></a><figcaption class="wp-caption-text">Rabin-Karp can detect plagiarism efficiently!</figcaption></figure></p>
<p>2. Not faster than brute force matching in theory, but in practice its complexity is O(n+m)!<br />
3. With a good hashing function it can be quite effective and it's easy to implement!</p>
<h3>2 Reasons Why Rabin-Karp is Not Cool</h3>
<p>1. There are lots of string matching algorithms that are faster than O(n+m)<br />
2. It’s practically as slow as brute force matching and it requires additional space</p>
<h2>Final Words</h2>
<p>Rabin-Karp is a great algorithm for one simple reason - it can be used to match against multiple pattern. This makes it perfect to detect plagiarism even for larger phrases. </p>
<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/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/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/02/computer-algorithms-rabin-karp-string-searching/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Brute Force String Matching</title>
		<link>/2012/03/27/computer-algorithms-brute-force-string-matching/</link>
		<comments>/2012/03/27/computer-algorithms-brute-force-string-matching/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 07:21:41 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Bitap algorithm]]></category>
		<category><![CDATA[Boyer–Moore string search algorithm]]></category>
		<category><![CDATA[brute force algorithms]]></category>
		<category><![CDATA[Computer science]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[pre-processing]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[sequential search]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[String]]></category>
		<category><![CDATA[String algorithms]]></category>
		<category><![CDATA[string matching algorithm]]></category>
		<category><![CDATA[String searching algorithm]]></category>
		<category><![CDATA[Technology/Internet]]></category>
		<category><![CDATA[text processing software]]></category>

		<guid isPermaLink="false">/?p=2966</guid>
		<description><![CDATA[Introduction String matching is something crucial for database development and text processing software. Fortunately every modern programming language and library is full of functions for string processing that help us in our everyday work. However is great to understand their principles. String algorithms can be mainly divided into several categories. One of these categories is &#8230; <a href="/2012/03/27/computer-algorithms-brute-force-string-matching/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Brute Force String Matching</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<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/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/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="/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>String matching is something crucial for database development and text processing software. Fortunately every modern programming language and library is full of functions for string processing that help us in our everyday work. However is great to understand their principles.</p>
<p>String algorithms can be mainly divided into several categories. One of these categories is string matching.</p>
<p>When we come to string matching the most basic approach is what is known as brute force, which means just to check every single character from the text to match against the pattern. In general we have a text and a pattern (most commonly shorter than the text). What we need to do is to answer the question whether this pattern appears into the text.</p>
<h2>Overview</h2>
<p>The principles of brute force string matching are quite simple. We must check for a match between the first characters of the pattern with the first character of the text as on the picture bellow.</p>
<p><figure id="attachment_2977" style="width: 618px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/03/FirstStepBruteforcestringmatching.png"><img src="/wp-content/uploads/2012/03/FirstStepBruteforcestringmatching.png" alt="First step of brute force string matching" title="First step of brute force string matching" width="618" height="236" class="size-full wp-image-2977" srcset="/wp-content/uploads/2012/03/FirstStepBruteforcestringmatching.png 618w, /wp-content/uploads/2012/03/FirstStepBruteforcestringmatching-300x114.png 300w" sizes="(max-width: 618px) 100vw, 618px" /></a><figcaption class="wp-caption-text">We start by comparing the first characters of the text and the pattern!</figcaption></figure> <span id="more-2966"></span><br />
If they don’t match we move forward the second character of the text. Now we compare the first character of the pattern with the second character of the text. If they don’t match again we move forward until we get a match or until we reach the end of the text. </p>
<figure id="attachment_2982" style="width: 612px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/03/SecondStepBruteforcestringmatching.png"><img src="/wp-content/uploads/2012/03/SecondStepBruteforcestringmatching.png" alt="Second step of brute force string matching" title="Second step of brute force string matching" width="612" height="241" class="size-full wp-image-2982" srcset="/wp-content/uploads/2012/03/SecondStepBruteforcestringmatching.png 612w, /wp-content/uploads/2012/03/SecondStepBruteforcestringmatching-300x118.png 300w" sizes="(max-width: 612px) 100vw, 612px" /></a><figcaption class="wp-caption-text">Because the first character of the text and the pattern don&#039;t match, we move forward the second character of the text. Now we compare the second character of the text with the first character of the pattern!</figcaption></figure>
<p>In case they match we move forward the second character of the pattern comparing it with the “next” character of the text, as on the picture bellow.</p>
<figure id="attachment_2981" style="width: 617px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/03/ThirdStepBruteforcestringmatching.png"><img src="/wp-content/uploads/2012/03/ThirdStepBruteforcestringmatching.png" alt="Third step of  brute force string matching" title="Third step of  brute force string matching" width="617" height="235" class="size-full wp-image-2981" srcset="/wp-content/uploads/2012/03/ThirdStepBruteforcestringmatching.png 617w, /wp-content/uploads/2012/03/ThirdStepBruteforcestringmatching-300x114.png 300w" sizes="(max-width: 617px) 100vw, 617px" /></a><figcaption class="wp-caption-text">If case a character from the text match against the first character of the pattern we move forward to the second character of the pattern and the next character of the text!</figcaption></figure>
<p>Just because we have found a match between the first character from the pattern with some character of the text, doesn’t mean that the pattern appears in the text. We must move forward to see whether the full pattern is contained into the text. </p>
<figure id="attachment_2980" style="width: 619px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/03/MatchBruteforcestringmatching.png"><img src="/wp-content/uploads/2012/03/MatchBruteforcestringmatching.png" alt="Match in brute force string matching" title="Match in brute force string matching" width="619" height="229" class="size-full wp-image-2980" srcset="/wp-content/uploads/2012/03/MatchBruteforcestringmatching.png 619w, /wp-content/uploads/2012/03/MatchBruteforcestringmatching-300x110.png 300w" sizes="(max-width: 619px) 100vw, 619px" /></a><figcaption class="wp-caption-text">The pattern is matched!</figcaption></figure>
<h2>Implementation</h2>
<p>Implementation of brute force string matching is easy and here we can see a short PHP example. The bad news is that naturally this algorithm is quite slow.</p>
<pre lang="PHP">
function sub_string($pattern, $subject) 
{
	$n = strlen($subject);
	$m = strlen($pattern);
	
	for ($i = 0; i < $n-$m; $i++) {
		$j = 0;
		while ($j < $m &#038;&#038; $subject[$i+$j] == $pattern[$j]) {
			$j++;
		}
		if ($j == $m) return $i;
	}
	return -1;
}

echo sub_string('o wo', 'hello world!');

</pre>
<h2>Complexity</h2>
<p>As I said this algorithm is slow. Actually every algorithm that contains “brute force” in its name is slow, but to show how slow is string matching I can say that its complexity is O(n.m). Here <strong>n</strong> is the length of the text, while <strong>m</strong> is the length of the pattern.</p>
<figure id="attachment_2978" style="width: 600px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart1.png"><img src="/wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart1.png" alt="Brute force string matching complexity chart 1" title="Brute force string matching complexity chart 1" width="600" height="371" class="size-full wp-image-2978" srcset="/wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart1.png 600w, /wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart1-300x185.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a><figcaption class="wp-caption-text">For fixed pattern length of m = 5, we can see that even for relatively short text the time grows quickly!</figcaption></figure>
<p>In case we fix the length of the text and test against variable length of the pattern, again we get rapidly growing function.</p>
<figure id="attachment_2979" style="width: 600px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart2.png"><img src="/wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart2.png" alt="Brute force string matching complexity chart 2" title="Brute force string matching complexity chart 2" width="600" height="371" class="size-full wp-image-2979" srcset="/wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart2.png 600w, /wp-content/uploads/2012/03/BruteForceStringMatchingComplexityChart2-300x185.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a><figcaption class="wp-caption-text"> </figcaption></figure>
<h2>Application</h2>
<p>Brute force string matching can be very ineffective, but it can also be very handy in some cases. Just like the <a href="/2011/11/24/computer-algorithms-sequential-search/" title="Computer Algorithms: Sequential Search">sequential search</a>.</p>
<h3>It can be very useful ...</h3>
<ol>
<li>Doesn't require pre-processing of the text - Indeed if we search the text only once we don't need to pre-process it. Most of the algorithms for string matching need to build an index of the text in order to search quickly. This is great when you've to search more than once into a text, but if you do only once, perhaps (for short texts) brute force matching is great!</li>
<li>Doesn't require additional space - Because brute force matching doesn't need pre-processing it also doesn't require more space, which is one cool feature of this algorithm</li>
<li>Can be quite effective for short texts and patterns</li>
</ol>
<h3>It can be ineffective ...</h3>
<ol>
<li>If we search more than once the text - As I said in the previous section if you perform the search more than once it's perhaps better to use another string matching algorithm that builds an index and it's faster.</li>
<li>It's slow - In general brute force algorithms are slow and brute force matching isn't an exception.</li>
</ol>
<h2>Final Words</h2>
<p>String matching is something very special in software development and it is used in various cases, so every developer must be familiar with this topic.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<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/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/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="/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/03/27/computer-algorithms-brute-force-string-matching/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Computer Algorithms: Data Compression with Run-length Encoding</title>
		<link>/2012/01/09/computer-algorithms-data-compression-with-run-length-encoding/</link>
		<comments>/2012/01/09/computer-algorithms-data-compression-with-run-length-encoding/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 09:08:06 +0000</pubDate>
		<dc:creator><![CDATA[Stoimen]]></dc:creator>
				<category><![CDATA[algorithms]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[Algorithmic efficiency]]></category>
		<category><![CDATA[binary search]]></category>
		<category><![CDATA[Bzip2]]></category>
		<category><![CDATA[Data compression]]></category>
		<category><![CDATA[data compression algorithm]]></category>
		<category><![CDATA[data compression algorithms]]></category>
		<category><![CDATA[faster services]]></category>
		<category><![CDATA[Google Inc.]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Lossless data compression]]></category>
		<category><![CDATA[lossless data compression algorithm]]></category>
		<category><![CDATA[Lossy compression]]></category>
		<category><![CDATA[programmer]]></category>
		<category><![CDATA[run-length algorithm]]></category>
		<category><![CDATA[Run-length encoding]]></category>
		<category><![CDATA[search algorithms]]></category>
		<category><![CDATA[Technology/Internet]]></category>
		<category><![CDATA[This algorithm]]></category>
		<category><![CDATA[virtual machine]]></category>
		<category><![CDATA[web server]]></category>

		<guid isPermaLink="false">/?p=2594</guid>
		<description><![CDATA[Introduction No matter how fast today&#8217;s computers and networks are, the users will constantly need faster and faster services. To reduce the volume of the transferred data we usually use some sort of compression. That is why this computer sciences area will be always interesting to research and develop. There are many data compression algorithms, &#8230; <a href="/2012/01/09/computer-algorithms-data-compression-with-run-length-encoding/" class="more-link">Continue reading <span class="screen-reader-text">Computer Algorithms: Data Compression with Run-length Encoding</span> <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href="/2012/05/03/computer-algorithms-lossy-image-compression-with-run-length-encoding/" rel="bookmark" title="Computer Algorithms: Lossy Image Compression with Run-Length Encoding">Computer Algorithms: Lossy Image Compression with Run-Length Encoding </a></li>
<li><a href="/2012/01/30/computer-algorithms-data-compression-with-relative-encoding/" rel="bookmark" title="Computer Algorithms: Data Compression with Relative Encoding">Computer Algorithms: Data Compression with Relative Encoding </a></li>
<li><a href="/2012/01/16/computer-algorithms-data-compression-with-bitmaps/" rel="bookmark" title="Computer Algorithms: Data Compression with Bitmaps">Computer Algorithms: Data Compression with Bitmaps </a></li>
<li><a href="/2012/01/23/computer-algorithms-data-compression-with-diagram-encoding-and-pattern-substitution/" rel="bookmark" title="Computer Algorithms: Data Compression with Diagram Encoding and Pattern Substitution">Computer Algorithms: Data Compression with Diagram Encoding and Pattern Substitution </a></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<h2>Introduction</h2>
<p>No matter how fast today&#8217;s computers and networks are, the users will constantly need faster and faster services. To reduce the volume of the transferred data we usually use some sort of compression. That is why this computer sciences area will be always interesting to research and develop.</p>
<p>There are many data compression algorithms, some of them lossless, others lossy, but their main goal aways will be to spare storage space and traffic. These algorithms are very useful when talking about data transfer between two distant places. Perhaps the best example is the transfer between a web server and a browser.</p>
<p>In the last few years a lot of research has been done on compressing files, executed on the client side. Such files are javascript, css, htmls and images. In fact servers and clients already have some techniques to compress data, like using <a href="http://www.gzip.org/" title="The gzip home page" target="_blank">GZIP</a> for instance, that can dramatically decrease the transfer. In the other hand there are lots of tools and tricks in order to decrease the size of the data.</p>
<p>Actually when a file is executed by the client&#8217;s virtual machine, it doesn&#8217;t matter how &#8220;beautifully&#8221; it is formatted from a programmer&#8217;s point of view. Thus the spaces, tabs and the new lines don&#8217;t bring any significant information for the environment. That is why such compressing tools like <a href="http://developer.yahoo.com/yui/compressor/" title="YUI Compressor" target="_blank">YUI Compressor</a>, <a href="http://code.google.com/closure/compiler/" title="Closure Compiler - Google Code" target="_blank">Google Closure Compiler</a>, etc. remove those symbols. Well, they can achieve even more in order to improve the compression rate. In this post I won&#8217;t cover this, but this shows how important data compression algorithms are.</p>
<p>It would be great if we could just compress data with some tool. Unfortunately this is not the case and usually the compression rate depends on the data itself. It is obvious that the choice of data compression algorithm depends mainly on the data and first of all we must explore the data.</p>
<p>Here I&#8217;ll cover one very simple lossless data compression algorithm called &#8220;run-length encoding&#8221; that can be very useful in some cases.</p>
<figure id="attachment_2618" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/01/Run-lengthEncoding1.png"><img src="/wp-content/uploads/2012/01/Run-lengthEncoding1.png" alt="Run-length Encoding" title="Run-length Encoding" width="620" class="size-full wp-image-2618" srcset="/wp-content/uploads/2012/01/Run-lengthEncoding1.png 978w, /wp-content/uploads/2012/01/Run-lengthEncoding1-300x129.png 300w" sizes="(max-width: 978px) 100vw, 978px" /></a><figcaption class="wp-caption-text"> </figcaption></figure>
<h2>Overview</h2>
<p>This algorithm consists of replacing large sequences of repeating data with only one item of this data followed by a counter showing how many times this item is repeated. To become clearer let’s see a string example.</p>
<pre lang="PHP">
aaaaaaaaaabbbaxxxxyyyzyx
</pre>
<p>This string&#8217;s length is <strong>24</strong> and as we can see there are lots of repetitions. Using the run-length algorithm, we replace any run with shorter string followed by a counter.</p>
<pre lang="PHP">
a10b3a1x4y3z1y1x1
</pre>
<p>The length of this string is <strong>17</strong>, which is approximately <strong>70%</strong> of the initial length. <span id="more-2594"></span>Obviously this is not the optimal way to compress the given string. For instance we don&#8217;t need to use the digit “1” when the character is repeated only once. In some cases this approach can increase the length of the initial string which is exactly the opposite of what we need. In this case we’ll get the string bellow.</p>
<pre lang="PHP">
a10b3ax4y3zyx
</pre>
<p>Now the length of the resulting string is <strong>13</strong>, which is <strong>54%</strong> of the initial length! A variation of the example above is not to keep a counter of the repetitions of the character, but their position instead. Thus the initial string will be compressed as follows.</p>
<pre lang="PHP">
a0b10a13x14y18z21y22x23
</pre>
<p>Which of these two approaches you&#8217;ll use depends on the goal. In the second case we can achieve a good optimization of <a href="/2011/12/26/computer-algorithms-binary-search/" title="Computer Algorithms: Binary Search">binary search</a>.</p>
<p>It is clear that this algorithm is not only applicable on strings. We can achieve very good results on arrays. A typical example is the transfer of <a href="http://www.json.org/" title="JSON" target="_blank">JSON</a> from a server to a client. Then if there are large sequences of repeating data we can achieve great results.</p>
<h2>Implementation</h2>
<p>The implementation bellow is assuming that we&#8217;re compressing a string and it&#8217;s written on PHP. However the nature of this algorithm doesn&#8217;t restrict us to use only strings. As I said before with slight modifications we can use it with other data structures. It is important only to understand that the run-length algorithm is very useful on large sequences of repeating elements, no matter characters or array items.</p>
<pre lang="PHP">
$message = 'aaaaaaaaaabbbaxxxxyyyzyx';

function run_length_encode($msg)
{
	$i = $j = 0;
	$prev = '';
	$output = '';
	
	while ($msg[$i]) {
		if ($msg[$i] != $prev) {
			
			if ($i) 
				$output .= $j;
				
			$output .= $msg[$i];
				
			$prev = $msg[$i];
			
			$j = 0;
		}
		$j++;
		$i++;
	}
	
	$output .= $j;
	
	return $output;
}

// a10b3a1x4y3z1y1x1
echo run_length_encode($message);
</pre>
<p>And slightly optimized.</p>
<pre lang="PHP">
$message = 'aaaaaaaaaabbbaxxxxyyyzyx';

function run_length_encode($msg)
{
	$i = $j = 0;
	$prev = '';
	$output = '';
	
	while ($msg[$i]) {
		if ($msg[$i] != $prev) {
			
			if ($i && $j > 1) 
				$output .= $j;
				
			$output .= $msg[$i];
				
			$prev = $msg[$i];
			
			$j = 0;
		}
		$j++;
		$i++;
	}
	
	if ($j > 1)
		$output .= $j;
	
	return $output;
}

// a10b3ax4y3zyx
echo run_length_encode($message);
</pre>
<p>Finally a small change &#8211; now we store the position of the character.</p>
<pre lang="PHP">
$message = 'aaaaaaaaaabbbaxxxxyyyzyx';

function run_length_encode($msg)
{
	$i = 0;
	$prev = '';
	$output = '';
	
	while ($msg[$i]) {
		if ($msg[$i] != $prev) {
				
			$output .= $msg[$i] . $i;
				
			$prev = $msg[$i];
			
		}

		$i++;
	}
	
	return $output;
}

// a0b10a13x14y18z21y22x23
echo run_length_encode($message);
</pre>
<h2>Complexity and Data Compression</h2>
<p>We&#8217;re used to talk about complexity of an algorithm measuring time and we usually try to find the fastest implementation, like in search algorithms. Here it is not so important to compress data quickly, but to compress as much as possible so the output is as small as possible without lossing data. A great feature of run-length encoding is that this algorithm is easy to implement.</p>
<h2>Application</h2>
<p>We can use run-length encoding in many cases. It is commonly used to compress images and is very successful when we deal only with black and white images. Here I&#8217;ll cover another use case that I only mentioned above. Let&#8217;s say we have to transfer a very large array of data to our AJAX-powered application using JSON. Let&#8217;s say also that the data are some years, for instance the years of the premiere of a movie. There are lots of movies with a premiere in the same year, thus although the data is sorted, we actually can&#8217;t have any benefit. More important is that we have large sequences of data. Here we can use run-length encoding.</p>
<pre lang="PHP">
$data = array(
	0 	=> 1991,
	1 	=> 1991,
	...
	2223 	=> 1991,
	2224 	=> 1992,
	...
	19298 	=> 1995,
	19299 	=> 1996,
	...
);
</pre>
<p>As you can see to transfer the whole array can be a nightmare, especially on slow networks. It is better to compress it (i.e. with PHP&#8217;s <a href="http://php.net/manual/en/function.json-encode.php" title="PHP: json_encode" target="_blank">json_encode</a>).</p>
<pre lang="PHP">
// {"0":1991,"1":1991, ..., "2223":1991,"2224":1992, ..., "19298":1995,"19299":1996, ...}
echo json_encode($data);
</pre>
<p>After running run-length encoding we can receive something like the following array (note that these are only sample data and it&#8217;s up to you to decide which is the best format to store data).</p>
<pre lang="PHP">
$data = array(
	0 => array(1991, 2224),
	1 => array(1992, 3948),
	2 => array(1995, 2398),
	3 => array(1996, 3489),
);
</pre>
<p>And the JSON output.</p>
<pre lang="PHP">
// [[1991,2224],[1992,3948],[1995,2398],[1996,3489]]
echo json_encode($data);
</pre>
<p>Note that if the data is sorted we can achieve great success compressing it!!! This approach can be used for images, graphics or map coordinates.</p>
<p>This is only one example of how data compression can be useful in our daily work. Although the communication between the server and the client can be optimized and compressed, we can improve it. In other words we&#8217;re not always sure that the opposite side supports compression.</p>
<p>Well, it&#8217;s true that the client has to decompress the data, which can also be slow. Now in the first case we have only the time to transfer, as on the diagram bellow.</p>
<figure id="attachment_2609" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/01/DataTransferWithoutCompression.png"><img src="/wp-content/uploads/2012/01/DataTransferWithoutCompression.png" alt="Data Transfer Without Compression" title="Data Transfer Without Compression" width="620" class="size-full wp-image-2609" srcset="/wp-content/uploads/2012/01/DataTransferWithoutCompression.png 957w, /wp-content/uploads/2012/01/DataTransferWithoutCompression-300x54.png 300w" sizes="(max-width: 957px) 100vw, 957px" /></a><figcaption class="wp-caption-text">Time to transfer data without compression!</figcaption></figure>
<p>In the second case, we should sum the time for compression, transfer and decompression.</p>
<figure id="attachment_2610" style="width: 620px" class="wp-caption alignnone"><a href="/wp-content/uploads/2012/01/DataTransferwithCompression.png"><img src="/wp-content/uploads/2012/01/DataTransferwithCompression.png" alt="Data Transfer with Compression" title="Data Transfer with Compression" width="620" class="size-full wp-image-2610" srcset="/wp-content/uploads/2012/01/DataTransferwithCompression.png 953w, /wp-content/uploads/2012/01/DataTransferwithCompression-300x59.png 300w" sizes="(max-width: 953px) 100vw, 953px" /></a><figcaption class="wp-caption-text">Time to send data with compression!</figcaption></figure>
<p>All this is important, but in general data compression can be handy in many cases in our daily work. </p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href="/2012/05/03/computer-algorithms-lossy-image-compression-with-run-length-encoding/" rel="bookmark" title="Computer Algorithms: Lossy Image Compression with Run-Length Encoding">Computer Algorithms: Lossy Image Compression with Run-Length Encoding </a></li>
<li><a href="/2012/01/30/computer-algorithms-data-compression-with-relative-encoding/" rel="bookmark" title="Computer Algorithms: Data Compression with Relative Encoding">Computer Algorithms: Data Compression with Relative Encoding </a></li>
<li><a href="/2012/01/16/computer-algorithms-data-compression-with-bitmaps/" rel="bookmark" title="Computer Algorithms: Data Compression with Bitmaps">Computer Algorithms: Data Compression with Bitmaps </a></li>
<li><a href="/2012/01/23/computer-algorithms-data-compression-with-diagram-encoding-and-pattern-substitution/" rel="bookmark" title="Computer Algorithms: Data Compression with Diagram Encoding and Pattern Substitution">Computer Algorithms: Data Compression with Diagram Encoding and Pattern Substitution </a></li>
</ol></p>
</div>
]]></content:encoded>
			<wfw:commentRss>/2012/01/09/computer-algorithms-data-compression-with-run-length-encoding/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>
