Normal quotes

This commit is contained in:
James Gregory 2013-12-30 18:34:31 +11:00
commit 18011c595a
352 changed files with 6040 additions and 6040 deletions

View file

@ -5,7 +5,7 @@
### The Boyer-Moore Algorithm {#Heading4}
All our *a priori* knowledge of string searching is stated above, but
there’s another sort of knowledge—knowledge that’s generated
there's another sort of knowledge—knowledge that's generated
dynamically. As we search through the buffer, we acquire information
each time we check for a match. One sort of information that we acquire
is based on partial matches; we can often skip ahead after partial
@ -14,23 +14,23 @@ already implicitly done a comparison of the partially matched buffer
characters with all possible pattern start locations that overlap those
partially-matched bytes.
If that makes your head hurt, it should—and don’t worry. This line of
If that makes your head hurt, it should—and don't worry. This line of
thinking, which is the basis of the Knuth-Morris-Pratt algorithm and
half the basis of the Boyer-Moore algorithm, is what gives Boyer-Moore
its reputation for inscrutability. That reputation is well deserved for
this aspect (which I will not discuss further in this book), but there’s
another part of Boyer-Moore that’s easily understood, easily
this aspect (which I will not discuss further in this book), but there's
another part of Boyer-Moore that's easily understood, easily
implemented, and highly effective.
Consider this: We’re searching for the pattern “ABC,” beginning the
search at the start (offset 0) of a buffer containing “ABZABC.” We match
on ‘A,’ we match on ‘B,’ and we mismatch on ‘C’; the buffer contains a
‘Z’ in this position. What have we learned? Why, we’ve learned not only
that the pattern doesn’t match the buffer starting at offset 0, but also
that it can’t possibly match starting at offset 1 or offset 2, either!
After all, there’s a ‘Z’ in the buffer at offset 2; since the pattern
doesn’t contain a single ‘Z,’ there’s no way that the pattern can match
starting at *any* location from which it would span the ‘Z’ at offset 2.
Consider this: We're searching for the pattern "ABC," beginning the
search at the start (offset 0) of a buffer containing "ABZABC." We match
on ‘A,' we match on ‘B,' and we mismatch on ‘C'; the buffer contains a
‘Z' in this position. What have we learned? Why, we've learned not only
that the pattern doesn't match the buffer starting at offset 0, but also
that it can't possibly match starting at offset 1 or offset 2, either!
After all, there's a ‘Z' in the buffer at offset 2; since the pattern
doesn't contain a single ‘Z,' there's no way that the pattern can match
starting at *any* location from which it would span the ‘Z' at offset 2.
We can just skip straight from offset 0 to offset 3 and continue, saving
ourselves two comparisons.
@ -41,8 +41,8 @@ Look at it differently, though: What if we compare the pattern starting
with the last (rightmost) byte, rather than the first (leftmost) byte?
In other words, what if we compare from high memory toward low, in the
direction in which string instructions go after the **STD** instruction?
After all, we’re comparing one set of bytes (the pattern) to another set
of bytes (a portion of the buffer); it doesn’t matter in the least in
After all, we're comparing one set of bytes (the pattern) to another set
of bytes (a portion of the buffer); it doesn't matter in the least in
what order we compare them, so long as all the bytes in one set are
compared to the corresponding bytes in the other set.
@ -51,25 +51,25 @@ compared to the corresponding bytes in the other set.
------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
We learn nothing new from a mismatch on the leftmost character, except
that the pattern can’t match starting at that location. A mismatch on
that the pattern can't match starting at that location. A mismatch on
the rightmost character, however, tells us about the possibilities of
the pattern matching starting at every buffer location from which the
pattern spans the mismatch location. If the mismatched character in the
buffer doesn’t appear in the pattern, then we’ve just eliminated not one
buffer doesn't appear in the pattern, then we've just eliminated not one
potential match, but as many potential matches as there are characters
in the pattern; that’s how many locations there are in the buffer that
in the pattern; that's how many locations there are in the buffer that
*might* have matched, but have just been shown not to, because they
overlap the mismatched character that doesn’t belong in the pattern. In
overlap the mismatched character that doesn't belong in the pattern. In
this case, we can skip ahead by the full pattern length in the buffer!
This is how we can outperform even **REPNZ SCASB; REPNZ SCASB** has to
check every byte in the buffer, but Boyer-Moore doesn’t.
check every byte in the buffer, but Boyer-Moore doesn't.
Figure 14.1 illustrates the operation of a Boyer-Moore search when the
rightcharacter of the search pattern (which is the first character
that’s compared at each location because we’re comparing backwards)
that's compared at each location because we're comparing backwards)
mismatches with a buffer character that appears nowhere in the pattern.
Figure 14.2 illustrates the operation of a partial match when the
mismatch occurs with a character that’s not a pattern member. In this
mismatch occurs with a character that's not a pattern member. In this
case, we can only skip ahead past the mismatch location, resulting in an
advance of fewer bytes than the pattern length, and potentially as
little as the same single byte distance by which the standard search
@ -79,7 +79,7 @@ approach advances.
**Figure 14.1**  *Mismatch on first character checked.*
What if the mismatch occurs with a buffer character that *does* occur in
the pattern? Then we can’t skip past the mismatch location, but we can
the pattern? Then we can't skip past the mismatch location, but we can
skip to whatever location aligns the rightmost occurrence of that
character in the pattern with the mismatch location, as shown in Figure
14.3.
@ -91,9 +91,9 @@ a mismatch, we see what we can learn from the buffer character that
failed to match the pattern. Imagine that we move the pattern to the
right across the mismatch location until we find a start location that
the mismatch does not eliminate as a possible match for the pattern. If
the mismatch character doesn’t appear in the pattern, the pattern can
the mismatch character doesn't appear in the pattern, the pattern can
move clear past the mismatch location. Otherwise, the pattern moves
until a matching pattern byte lies atop the mismatch. That’s all there
until a matching pattern byte lies atop the mismatch. That's all there
is to it!
![](images/14-02.jpg)\