×

Java Boyer Moore

A string searching or matching technique called the Boyer-Moore algorithm was created in 1977 by Robert S. Boyer and J. Strother Moore. It is the most popular and effective string-matching algorithm. Compared to the brute-force algorithm, it is substantially faster. The Boyer-Moore algorithm, its features, and its application in a Java program will all be covered in this article. It has a temporal complexity of O(nm+s). In most applications, the Boyer-Moore algorithm is the most efficient string-matching algorithm. In text editors, the «search» and «substitute» commands frequently use a simplified version of the algorithm or the entire algorithm.

Worst-case scenario

T=ssssssss……sssssss………ssssssss

P=psssssssss

The above sequence can be found in images and DNA sequences.

Characteristics of the Boyer Moore Algorithm

  • From right to left, it compares each character;
  • O(m+) time and space complexity characterize the pre-processing stage.
  • The searching step has an O(mn) complexity.
  • In the worst scenario, it compares 3n text characters when looking for a non-periodic pattern.
  • The complexity with the best performance is O(n/m).

The algorithm is based on the two heuristics listed below:

  • Character-Jump Heuristics
  • Looking-Glass Heuristics

Let's examine how the Boyer-Moore algorithm works.

The Boyer-Moore algorithm's operation

The method begins tracing characters from the pattern's rightmost character and advances leftward. It employs two pre-computed functions that shift the characters to the right and left, respectively, in the event of any mismatch and complete pattern matching. The good-suffix shift (also known as the matching shift) and the bad-character shift (or occurrence shift) are the names of these two pre-computed shift functions.

Note: Characters should be compared in a right-to-left sequence and aligned left to right to match the pattern.

Bad Character Shift

Skip alignment when there is a mismatch up until one of the following situations does not exist:

  1. Mismatch turns into a match
  2. P avoids mismatching characters

Take the text (T) and pattern (P) shown below as examples.

Boyer Moore Java

Start comparing the pattern now.

Step 1: First, align characters from left to right and compare them from right to left.

We can see that the last three characters of P correspond to those in T. T, the fourth character, is mismatched. As per the above guideline, skip alignment until a mismatch becomes a match. The seventh character (C) in P matched with C in T.

Boyer Moore Java

The above-displayed image shows the partial match.

Step 2: Move three characters to the right to match the pattern.

Compare the characters once more, this time from right to left, after moving. It matches the first character. We see that the character A is absent from the position to the left of P. P then shifts to the past mismatch character (A) in T in this instance.

Boyer Moore Java

The above-displayed image shows the procedure through which P and T attain matches.

Step 3: If P is moved past the mismatched character, we get,

Boyer Moore Java

From the above-displayed image, the pattern is matched. The sequence “CCTTTTGC” matches in both the T and P.

Note: The bad-character shift may not be good. Given that the Boyer-Moore method applies the maximum (skip characters) between the good-suffix shift and bad-character shift, it is appropriate to shift characters in this manner.

Good-Suffix Shift

Let's say that an inner loop matches the substring t. If so, skip characters up until:

  1. No mismatches exist between P and t.
  2. P moves past t.

Consider the following pattern as an example.

Boyer Moore Java

Step 1: Go from right to left and compare the characters. We can see that the last three characters of P correspond to characters in T denoted by t.

Boyer Moore Java

The above-displayed image shows the partial match.

Step 2: Continue until there is no match between P and t. The first four characters (from left to right) of P (C T T A C) correspond to the last five characters in t.

Boyer Moore Java

The above-displayed image shows the procedure through which P and t attain no matches.

Step 3: To get the match, skip three alignments. As a result, we get the match.

Boyer Moore Java

The above-displayed image shows the match. The sequence “CTTACTTAC” matches in both the T and P.

The two-shift functions described above can be defined as follows:

The good-suffix shift function is stored in a table of size m+1 called “bmGs”. The table “bmGs” is computed using a table “suff” defined as follows:

for 1 ? i < m, suff[i]=max{k : x[i-k+1 .. i]=x[m-k .. m-1]} 

The bad-character shift function is stored in a table bmBc of size s. For c in ∑:

bmBc[c] = min{i : 1 ? i <m-1 and x[m-1-i]=c} if c occurs in x, m otherwise. 

Pattern Matching Example Using Boyer Moore

Think about the following pattern.

Boyer Moore Java

Let's begin matching.

Step 1: Characters should be compared from right to left. The first character is mismatched, as G does not match with T.

Boyer Moore Java

Step 2: Skip the following few characters until we find a match. After six characters, a match is made. The good suffix shift rule will not be applicable in this case.

Boyer Moore Java

P moves past mismatch character (i.e. G), according to bad character shift.

Boyer Moore Java

Step 3: Compare characters once more from right to left. We can observe that P's first three characters match (t) with T, but its fourth character does not.

Boyer Moore Java

Both the bad and good character suffix can be used in this situation. When the bad character suffix is used, only one character is skipped. The good character suffix ignores two alignments when used. Therefore, since the algorithm says to skip additional alignments, we will use the good character suffix. Consequently, we omit two alignments.

Boyer Moore Java

Three characters of alignment are changed, and the result is:

Boyer Moore Java

Here, we can see that C is missing from P's area to the left. Good character alignments skip seven alignments, while bad character alignments skip two alignments.

Step 4: We can observe that the string is matched after changing a few characters.

Boyer Moore Java

We skipped 15 alignments in the earlier pattern, and 11 T characters were ignored.

Boyer Moore Pre-processing Phases

The following definition applies to calculated skips for the patterns T: A A T C A A T A G C and P: T C G C. The bad character shift function was employed in the above pattern.

Boyer Moore Java

The above table (characters) shows the number of skip alignments.

Pseudo Code for the Boyer Moore Algorithm

BoyerMooreMatch(H, T, ?)  
K<- lastOccurenceFunction(T, ?)  
i <- m-1  
j <- m-1  
repeat  
                    if H[i]=T[j]  
                             if j=0  
                                  return i {match at i}  
                             else  
                                  i <- i-1  
                                  j <- j-1  
                    else  
                         {character-jump}  
                         K<-K[H[i]]  
                         i <- i +m -min(j, 1+ l)  
                         j <- m-1  
until i>n-1  
return-1 {no match}  

Java Program for Pattern Searching

Let's look at the pattern-finding Java program. The brute-force string searching algorithm is implemented in the following program.

File name: PatternSearchingExample.java

import java.util.HashMap;  
import java.util.Map;  
public class PatternSearchingExample  
{  
/**  
* @example text -- trace the text to see if it contains pattern 
* @example pattern -- look for this text inside the text parameter 
* @return -- return index of the first match or -1 if not found 
*/  
public static int findBruteForce(char[] text, char[] pattern)   
{  
System.out.println("Brute force looking for " + String.valueOf(pattern) + " in " + String.valueOf(text)) ;  
int n = text.length ;  
int m = pattern.length ;  
//checks if the string is empty  
if (m == 0) return 0 ;  
//brute force it -- loop over all characters in text O(n)  
for (int i=0;i<=n-m;i++)   
{ //index into the text  
//loop over all characters in pattern while characters match O(m)  
//index into the pattern  
int k = 0 ;   
while (k<m && text[i+k] == pattern[k])   
{  
k++ ;  
}  
//if at the end of the pattern, then found match starting at index i in text  
if (k==m)   
{  
System.out.println("\tFound match in the given text at index " + i) ;  
return i ;  
}  
}  
//if a match is not found  
System.out.println("\tNo match found in the given text.") ;  
return -1 ;  
}  
/** 
 
* @example text -- search this text to see if it contains pattern 
* @example pattern -- look for this text inside the text parameter 
* @return -- return index of the first match or -1 if not found 
*/  
public static int findBoyerMoore(char[] text, char[] pattern)   
{  
System.out.println("Boyer-Moore looking for " + String.valueOf(pattern) + " in " + String.valueOf(text)) ;  //valueOf method is used
int n = text.length ;  // n stores length of the text
int m = pattern.length ;  
// Test for empty string  
if (m == 0) return 0 ;  
// Initialization, create Map of last position of each character = O(n)  
Map<Character, Integer> last = new HashMap<>() ;  //Map
for (int i = 0; i < n; i++)   
{  
// set all chars, by default, to -1      
last.put(text[i], -1) ;     
}          
for (int i = 0; i < m; i++)   
{  
// update last seen positions      
last.put(pattern[i], i) ;   
}  
//Start with the end of the pattern aligned at index m-1 in the text.   
//index into the text  
int i = m - 1 ;    
// index into the pattern  
int k = m - 1 ;    
while (i < n)   
{   
if (text[i] == pattern[k])   
{  
// match! return i if complete match; otherwise, keep checking      
if (k == 0)   
{  
System.out.println("\tFound match in the given text at index " + i) ;  
return i ;   
}  
i = i - 1 ; 
k--;   
}   
else   
{ // jump step + restart at end of pattern  
//iterate over the text   
i += m - Math.min(k, 1 + last.get(text[i])) ;    
//move to the end of the pattern  
k = m - 1 ;   
}  
}  
System.out.println("\tNo match found in the given text.") ;  
// prints as not found  
return -1 ;   
}  
public static void main(String args[])   
{  
char[] text = "abcfefabddef".toCharArray() ;  //string to character array
char[] pattern = "abddef".toCharArray() ;  //string to character array
//function calling  
findBruteForce(text,pattern) ;  //calls the findBruteForce function
findBoyerMoore(text,pattern) ;          //calls the findBruteForce function
}  
}   

Output

Boyer Moore Java

The above-displayed image is the output for the above program, and The output says that "abddef” is present in the “abcfefabddef” at index 6.

Let's use a Java program to implement the algorithm.

The Boyer Moore Java Program

Let's use a Java program to implement the Boyer-Moore algorithm and search pattern.

Program 1

Filename: BoyerMooreImplementation.java

public class BoyerMooreImplementation  
{  
static int NO_OF_CHARS = 256;   
static int max (int a, int b)   
{   
return (a > b)? a: b;   
}   
static void badCharHeuristic( char []str, int size, int badchar[])   
{   
int i;   
for (i = 0; i < NO_OF_CHARS; i++)   
badchar[i] = -1;   
for (i = 0; i < size; i++)   
badchar[(int) str[i]] = i;   
}   
static void search( char txt[],  char pat[])   
{   
int m = pat.length;   
int n = txt.length;   
int badchar[] = new int[NO_OF_CHARS];   
//function calling  
badCharHeuristic(pat, m, badchar);   
int s = 0;    
while(s <= (n - m))   
{   
int j = m-1;   
while(j >= 0 && pat[j] == txt[s+j])   
j--;   
if (j < 0)   
{   
System.out.println("Patterns occur at character = " + s);   
s += (s+m < n)? m-badchar[txt[s+m]] : 1;   
}   
else  
s += max(1, j - badchar[txt[s+j]]);   
}   
}   
public static void main(String args[])   
{   
//text in which pattern occurs  
char txt[] = "123651266512".toCharArray();   
//pattern to search  
char pat[] = "12".toCharArray();   
search(txt, pat);   
}   
}  

Output

Boyer Moore Java

Let's look at another Java program where we have distinct logic for pattern finding implemented. The code that follows next determines whether the text contains the required pattern.

Program 2

Filename: BoyerMooreExample.java

public class BoyerMooreExample  
{  
public static void main(String args[])   
{  
        System.out.println("Matching Pattern");  
        test("aabbccdef", "cde", 0);  
        test("zzzzaaapppxyzabc", "pqrs", 1);  
        test("mango", "ngo", 2);  
        test("abc", "d", -1);  
        test("catdog", "tdo", 2);  
        test("pqrsabcdxyzamnop", "cdxyza", 1);  
        test("cool", "", 0);  
        test("", "car", -1);  
}  
    public static void test(String text, String word, int exp)   
    {  
        char[] textC = text.toCharArray();  
        char[] wordC = word.toCharArray();  
        int result = bm(textC, wordC);  
        if(result == exp)  
            System.out.println("Pattern Matched");  
        else   
        {  
            System.out.println("Pattern Not Matched");  
            System.out.println("\ttext: " + text);  
            System.out.println("\tword: " + word);  
            System.out.println("\texp: " + exp + ", res: " + result);  
        }//end of else  
    }//end of function  
    public static int[] makeD1(char[] pat)   
    {  
        int[] table = new int[255];  
        for(int i=0; i<255; i++)  
            table[i] = pat.length;  
        for(int i=0; i<pat.length-1; i++)  
            table[pat[i]] = pat.length-1-i;  
        return table;  
    }//end of the function  
    public static boolean isPrefix(char[] word, int pos)   
    {  
        int suffixlen = word.length - pos;  
        for(int i=0; i<suffixlen; i++)  
            if(word[i] != word[pos+i])  
                return false;  
        return true;  
    }//end of the function  
    public static int suffix_length(char[] word, int pos)   
    {  
        int i;  
        for(i=0; ((word[pos-i] == word[word.length-1-i]) & (i < pos)); i++)  
            {  
                  
            }//end of for loop  
        return i;  
    }//end of the function   
    public static int[] makeD2(char[] pat)   
    {  
        int[] delta2 = new int[pat.length];  
        int p;  
        int last_prefix_index = pat.length - 1;  
        for(p = pat.length-1; p>=0; p--)   
        {  
            if(isPrefix(pat, p+1))  
                last_prefix_index = p+1;  
            delta2[p] = last_prefix_index + (pat.length-1-p);  
        }//end of for loop  
        for(p=0; p<pat.length-1; p++)   
        {  
            int slen = suffix_length(pat, p);  
            if(pat[p-slen] != pat[pat.length-1-slen])  
                delta2[pat.length-1-slen] = pat.length-1-p+slen;  
        }//end of for loop  
        return delta2;  
    }//end of function  
    public static int bm(char[] string, char[] pat)   
    {  
        int[] d1 = makeD1(pat);  
        int[] d2 = makeD2(pat);  
        int i = pat.length-1;  
        while(i < string.length)   
        {  
            int j = pat.length-1;  
            while(j>=0 && (string[i] == pat[j]))   
            {  
                i--; //decrement i by 1  
                j--; //decrement j by 1  
            }//end of while  
            if(j < 0)  
                return (i+1);  
            i += Math.max(d1[string[i]], d2[j]);  
        } //end of while  
        return -1;  
    }//end of the function  
}  

Output

Boyer Moore Java

Related Topics

Program to Find Square Root of a Number Without sqrt Method in Java

The Java Math class sqrt () function can be used to determine the square root of a number. In this section, we'll write a Java program to find a number's...

3 minutes read.

Various operations on HashSet in Java

In this article, you will be acknowledged about what is a HashSet in java and what are its operations in java programming language. The HashSet is a crucial part of...

3 minutes read.

Java Enumeration

In a computer language, enumerations express a set of named constants. For instance, the four suits in a deck of playing cards could be represented by the enumerators Club, Diamond,...

4 minutes read.

Java 9 Interface Private Method

Java 9 provides us the facility to include private methods inside the java interface. In java 8 and earlier versions, we are supposed to use only constant variables and abstract...

3 minutes read.

Java Integer toOctalString() method

The toOctalString() method of Java Integer class returns a string representing the specified int argument as an unsigned integer in base 8. Syntax public static String toOctalString (int  i) Parameters The parameter ‘i’ represents...

1 minute read.

PriorityQueue in Java

PriorityQueue in Java A PriorityQueue is a member of the Java Collection Framework and is used when the values are needed to be processed based on priority. Priority queue operates similar to...

8 minutes read.

Java Math toIntExact() Method

The toIntExact() method of Java Math class returns the int value of the given long argument, throwing an exception if the value overflows an int. Syntax: public static int toIntExact (long value) Parameters: The...

2 minutes read.

Java Integer hashCode() method

The hashCode()  method of Java Integer class returns a hash code for this Integer.  Syntax public int hashCode() public static int hashCode(int value)  Parameters The parameter ‘value’ represents a value whose hash code...

1 minute read.

Java Database Connectivity with MySQL

In this tutorial, we will learn how to connect Database with MySQL in Java. 5 Steps to Connect to the Database in Java Load the driver (or) Register the driver classEstablish a...

4 minutes read.

Java Integer lowestOneBit()

The lowestOneBit () method of Java Integer class returns an int value with at most a single one-bit, in the position of the lowest-order one-bit in the specified int value.  Syntax public...

2 minutes read.

Various Operation on Queue using Linked List in Java

We keep track of front and rear pointers in a queue data structure. The head of the line points to the first item, and the back to the last. Rear is...

3 minutes read.

Generic queue in Java

Before understanding how to implement a generic queue in java, one must know about generics and queue in java. Generics in Java Generics are parameterized types. The goal is to enable type...

6 minutes read.

Level order Traversal of a Binary Tree in Java

In Java, a level order traversal of a tree structure is also referred to as the breadth-first traversal of the binary tree. Regarding the subsequent binary tree: Level order traversal is as...

5 minutes read.

Java AWT

Java AWT Java programming is used to develop different types of applications like window-based applications, web applications, Enterprise applications, or mobile applications. For creating standalone applications, Java AWT API is used....

11 minutes read.

How to compare characters in Java

In this tutorial, we will learn about how to compare characters in Java. To compare characters in Java, we will learn about what is a character in Java Char The character is...

4 minutes read.

Java Boolean hashCode() Method

The hashCode() method of Boolean class returns the hash code for the specified Boolean object or the given Boolean value. Syntax public int hashCode()public int hashCode(boolean value) Parameters The parameter ‘value’ represents the value...

2 minutes read.

Java Command not found

Java Command not found error is displayed if Java is not installed on the computer or if the command prompt cannot find Java.exe to run the program. Our Java software...

3 minutes read.

Java String lastIndexOf() method

Java String lastIndexOf() method returns last index of character or substring in a String. Syntax: Method Description int lastIndexOf(int ch)It returns last index position for the given char valueint lastIndexOf(int ch, int...

2 minutes read.

Blocking Queue in Java Example

Let's first briefly comprehend queue before moving on to the topic of "Blocking Queue." A queue seems to be an orderly list of items in which elements are added from...

8 minutes read.

Java Read File to String

There are different ways to deal with forming and examining a text record. This is normal while dealing with various applications. There are different ways to deal with looking at a...

6 minutes read.