abrash-black-book/14-01.html

106 lines
8.6 KiB
HTML

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="vsisbn" content="1576101746" />
<meta name="vstitle" content="Michael Abrash's Graphics Programming Black Book, Special Edition" />
<meta name="vsauthor" content="Michael Abrash" />
<meta name="vspublisher" content="The Coriolis Group" />
<meta name="vspubdate" content="07/01/97" />
<meta name="vscategory" content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development" />
<title>Michael Abrash's Graphics Programming Black Book Special Edition: Boyer-Moore String Searching</title>
<meta name="chapter" content="14" />
<meta name="pages" content="260-263" />
</head>
<body>
<center>
<table border="1">
<tr>
<td>
<a href="13-04.html">Previous</a>
</td>
<td>
<a href="index.html">Table of Contents</a>
</td>
<td>
<a href="14-02.html">Next</a>
</td>
</tr>
</table>
</center>
<h2 id="Heading1">Chapter 14<br />
Boyer-Moore String Searching</h2>
<h3 id="Heading2">Optimizing a Pretty Optimum Search Algorithm</h3>
<p>When you seem to be stumped, stop for a minute and <i>think.</i> All the information you need may be right in front of your nose if you just look at things a little differently. Here&rsquo;s a case in point:</p>
<p>When I was in college, I used to stay around campus for the summer. Oh, I&rsquo;d take a course or two, but mostly it was an excuse to hang out and have fun. In that spirit, my girlfriend, Adrian (<i>not</i> my future wife, partly for reasons that will soon become apparent), bussed in to spend a week, sharing a less-than-elegant $150 per month apartment with me and, by necessity, my roommate.</p>
<p>Our apartment was pretty much standard issue for two male college students; maybe even a cut above. The dishes were usually washed, there was generally food in the refrigerator, and nothing larger than a small dog had taken up permanent residence in the bathroom. However, there was one sticking point (literally): the kitchen floor. This floor&mdash;standard tile, with a nice pattern of black lines on an off-white background (or so we thought)&mdash;had never been cleaned. By which I mean that I know for a certainty that <i>we</i> had never cleaned it, but I suspect that it had in fact not been cleaned since the Late Jurassic, or possibly earlier. Our feet tended to stick to it; had the apartment suddenly turned upside-down, I think we&rsquo;d all have been hanging from the ceiling.</p>
<p>One day, my roommate and I returned from a pick-up basketball game. Adrian, having been left to her own devices for a couple of hours, had apparently kept herself busy. &ldquo;Notice anything?&rdquo; she asked, with an edge to her voice that suggested we had damned well better.</p>
<p>&ldquo;Uh, you cooked dinner?&rdquo; I guessed. &ldquo;Washed the dishes? Had your hair done?&rdquo; My roommate was equally without a clue.</p>
<p>She stamped her foot (really; the only time I&rsquo;ve ever seen it happen), and said, &ldquo;No, you jerks! The kitchen floor! Look at the floor! I cleaned it!&rdquo;</p>
<p>The floor really did look amazing. It was actually all white; the black lines had been grooves filled with dirt. We assured her that it looked terrific, it just wasn&rsquo;t that obvious until you knew to look for it; anyone would tell you that it wasn&rsquo;t the kind of thing that jumped out at you, but it really was great, no kidding. We had almost smoothed things over, when a friend walked in, looked around with a start, and said, &ldquo;Hey! Did you guys put in a new floor?&rdquo;</p>
<p>As I said, sometimes everything you need to know is right in front of your nose. Which brings us to Boyer-Moore string searching.</p>
<h3 id="Heading3">String Searching Refresher</h3>
<p>I&rsquo;ve discussed string searching earlier in this book, in Chapters 5 and 9. You may want to refer back to these chapters for some background on string searching in general. I&rsquo;m also going to use some of the code from that chapter as part of this chapter&rsquo;s test suite. For further information, you may want to refer to the discussion of string searching in the excellent <i>Algorithms in C,</i> by Robert Sedgewick (Addison-Wesley), which served as the primary reference for this chapter. (If you look at Sedgewick, be aware that in the Boyer-Moore listing on page 288, there is a mistake: &ldquo;j &gt; 0&rdquo; in the <b>for</b> loop should be &ldquo;j &gt;= 0,&rdquo; unless I&rsquo;m missing something.)</p>
<p>String searching is the simple matter of finding the first occurrence of a particular sequence of bytes (the pattern) within another sequence of bytes (the buffer). The obvious, brute-force approach is to try every possible match location, starting at the beginning of the buffer and advancing one position after each mismatch, until either a match is found or the buffer is exhausted. There&rsquo;s even a nifty string instruction, <b>REPZ CMPS,</b> that&rsquo;s perfect for comparing the pattern to the contents of the buffer at each location. What could be simpler?</p>
<p>We have some important information that we&rsquo;re not yet using, though. Typically, the buffer will contain a wide variety of bytes. Let&rsquo;s assume that the buffer contains text, in which case there will be dozens of different characters; and although the distribution of characters won&rsquo;t usually be even, neither will any one character constitute half the buffer, or anything close. A reasonable conclusion is that the first character of the pattern will rarely match the first character of the buffer location currently being checked. This allows us to use the speedy <b>REPNZ SCASB</b> to whiz through the buffer, eliminating most potential match locations with single repetitions of <b>SCASB.</b> Only when that first character does (infrequently) match must we drop back to the slower <b>REPZ CMPS</b> approach.</p>
<p>It&rsquo;s important to understand that we&rsquo;re assuming that the buffer is typical text. That&rsquo;s what I meant at the outset, when I said that the information you need may be under your nose.</p>
<table width="100%">
<tr>
<td align="left" valign="top" width="5%"><img src="images/i.jpg" /></td>
<td align="left" valign="top" width="95%"><small><i>Formally, you don&rsquo;t know a blessed thing about the search buffer, but experience, common sense, and your knowledge of the application give you a great deal of useful, if somewhat imprecise, information.</i></small></td>
</tr>
</table>
<p>If the buffer contains the letter &lsquo;A&rsquo; repeated 1,000 times, followed by the letter &lsquo;B,&rsquo; then the <b>REPNZ SCASB/REPZ CMPS</b> approach will be much slower than the brute-force <b>REPZ CMPS</b> approach when searching for the pattern &ldquo;AB,&rdquo; because <b>REPNZ SCASB</b> would match at every buffer location. You could construct a horrendous worst-case scenario for almost any good optimization; the key is understanding the usual conditions under which your code will work.</p>
<p>As discussed in Chapter 9, we also know that certain characters have lower probabilities of matching than others. In a normal buffer, &lsquo;T&rsquo; will match far more often than &lsquo;X.&rsquo; Therefore, if we use <b>REPNZ SCASB</b> to scan for the least common letter in the search string, rather than the first letter, we&rsquo;ll greatly decrease the number of times we have to drop back to <b>REPZ CMPS,</b> and the search time will become very close to the time it takes <b>REPNZ SCASB</b> to go from the start of the buffer to the match location. If the distance to the first match is N bytes, the least-common <b>REPNZ SCASB</b> approach will take about as long as N repetitions of <b>REPNZ SCASB.</b></p>
<p>At this point, we&rsquo;re pretty much searching at the speed of <b>REPNZ SCASB.</b> On the x86, there simply is no faster way to test each character in turn. In order to get any faster, we&rsquo;d have to check fewer characters&mdash;but we can&rsquo;t do that and still be sure of finding all matches. Can we?</p>
<p>Actually, yes, we can.</p>
<center>
<table border="1">
<tr>
<td>
<a href="13-04.html">Previous</a>
</td>
<td>
<a href="index.html">Table of Contents</a>
</td>
<td>
<a href="14-02.html">Next</a>
</td>
</tr>
</table>
</center>
<hr width="90%" size="1" noshade="noshade" />
<div align="center">
Graphics Programming Black Book &copy; 2001 Michael Abrash
</div>
</body>
</html>