Java Program to Implement Zhu–Takaoka String Matching Algorithm
Last Updated :
12 Sep, 2021
Zhu-Takaoka String Matching Algorithm is a Variant of Boyer Moore Algorithm for Pattern Matching in a String. There is a slight change in the concept of Bad Maps in this algorithm. The concept of Good Suffixes remains as same as that of Boyer Moore’s but instead of using a single character for Bad Shifts, now in this algorithm, we will be performing two shifts.
Hence, this algorithm provides a little speed over the Boyer’s one. Both Good suffixes and Two character Bad shifts can be used together in the code to give an extra edge in the performance of the Algorithm. We are discussing the idea of how to change the calculation of Bad Character Shifts for this algorithm and the idea of Good suffixes can be derived from Boyer’s algorithm.
Working of Algorithms:
At first, this algorithm starts the same as that of Boyer’s one starts i.e. comparing the pattern to the string from Right to Left. Hence, each character of the pattern is compared to that of string from Right to Left. So the starting index of the comparison should be the length of the pattern.
String : ABCDEFGH
Pattern: BCD
So the comparison should begin at the index of ‘C’ in string i.e. 2 (0-based indexing is used). So comparison starts at index = Length of Pattern – 1. If a match is found then the index is decremented till the matches are found. Once the match is not found then it’s time to make shifts for Bad Characters.
String : ABCDEFGH
Pattern: BCC
a) At index 2 String has Char ‘C’ and since Pattern[2]==’C’ so character match is found. So we are now going to check for previous indexes i.e. 1, 0. So at string[1] (which is equal to ‘B”), Pattern[1]!=’B’ So the match is not found and is the time to shift the characters.
Computing table for Bad Character Shifts (named ZTBC Table): This stage is a preprocessing stage i.e. should be done before starting the comparisons. Bad Character tables is a Hash Map which has all alphabets of Pattern as the keys and the value represents the number of shift the pattern should be given so that either:
- The mismatch becomes a match.
- The pattern passed that mismatched character of the string.
So in Zhu-Takaoka Algorithm, we are maintaining a 2-D array that can give the number of shifts based on the first two characters of the string from where the comparison had started. Hence, increasing the number of shifts and decreasing the number of comparisons which results in more increased performance.
Procedure: Logic building. The idea for computing the table is as depicted below:
The table is made using a 2D Array where all the columns and rows are named by the character of the Patterns. The table is initialized with the length of the pattern since if the pair of char is not found in the pattern then the only way is to pass the whole pattern through pass the mismatched character.
If pattern is = "ABCD"
The ZTBC = A B C D E...
A 4 4 4 4 4
B 4 4 4 4 4
C 4 4 4 4 4
D 4 4 4 4 4
E.....
Now if out of the two char if the second one is the starting character of the pattern then shifting the whole pattern is not the right idea we should make a match of the second char with the first one of the pattern. So we should shift the pattern by Len-1.
so For all i in size of array
ZTBC[i][pattern[0]] = len-1.
so ZTBC now looks like :
ZTBC = A B C D E....
A 3 4 4 4 4
B 3 4 4 4 4
C 3 4 4 4 4
D 3 4 4 4 4
E.....
Now if both characters are found consecutively in the pattern then we should shift the pattern only that much so that the pair of chars in string and pattern matches so.
for all i in array.size
ZTBC[pattern[i-1]][pattern[i]] = len-i-1 ; //This is the amount of shifts if two matching pair is found.
So finally ZTBC looks like
ZTBC = A B C D E ......
A 3 2 4 4 4
B 3 4 1 4 4
C 3 4 4 4 4
D 3 4 4 4 4
E.......
Illustration:
Hence, suppose a string and pattern is given as below:
String S = "ABCABCDE"
Pattern P = "ABCD"
It is descriptively shown with the help of visual arts below as follows:

So considering 0-Based indexing, we will begin at index 3
so s[3]!=P[3] // p[3]=='D' and S[3]=='A'
Hence, a mismatch occurs, and we will shift the array by
ZTBC[C][A] since last two consecutive char is CA in string.
So now we will shift the pattern by 3
Since ZTBC[C][A] == 3, and now we are at index 6 ( 3+3 )
And now we should again start a comparison of the string and pattern as in step 1, and then we would found a match of pattern in the string so print it. We found one occurrence. Now since continuing further, we should now shift by the last two char i.e. CD in String since they are only at the previous index. Hence, we should shift our pattern by 1 and continue the same process. Also, we can include the idea of Good Suffixes in this program to find the max number of shifts necessary and hence make our code’s performance better. The idea of Good Suffixes is the same as that in Boyer’s one. Hence, presenting a general formula for the above shifting idea we get If a mismatch occurs at Char of String. Say
Say S[i+m-k]!=P[m-k] //m is the size of pattern and j is the index of the start of matching .
Then the number of the shift should be given as:
ZTBC[S[i+m-2]][S[i+m-1]] // two consecutive char at the index where comparisons starts.
Example:
Java
import java.io.*;
import java.lang.*;
import java.util.*;
public class GFG {
public static String string = "ABCABCDEABCDEA" ;
public static String pattern = "ABCD" ;
public static int stringlen = 14 ;
public static int patternlen = 4 ;
public static int [][] ZTBC = new int [ 26 ][ 26 ];
public static void ZTBCCalculation()
{
int i, j;
for (i = 0 ; i < 26 ; ++i)
for (j = 0 ; j < 26 ; ++j)
ZTBC[i][j] = patternlen;
for (i = 0 ; i < 26 ; ++i)
ZTBC[i][pattern.charAt( 0 ) - 'A' ]
= patternlen - 1 ;
for (i = 1 ; i < patternlen - 1 ; ++i)
ZTBC[pattern.charAt(i - 1 ) - 'A' ]
[pattern.charAt(i) - 'A' ]
= patternlen - 1 - i;
}
public static void main(String args[])
{
int i, j;
ZTBCCalculation();
j = 0 ;
while (j <= stringlen - patternlen) {
i = patternlen - 1 ;
while (i >= 0
&& pattern.charAt(i)
== string.charAt(i + j))
--i;
if (i < 0 ) {
System.out.println( "Pattern Found at "
+ (j + 1 ));
j += patternlen;
}
else
j += ZTBC[string.charAt(j + patternlen - 2 )
- 'A' ]
[string.charAt(j + patternlen - 1 )
- 'A' ];
}
}
}
|
Output
Pattern Found at 4
Pattern Found at 9
Note:
- Runtime complexity is found to be O(stringlen*patternlen) For searching one and O(patterlen + (26*26)).
- Space Complexity is found to be O(26×26) which is constant nearly for large test cases.
Similar Reads
Java Program to Implement Bitap Algorithm for String Matching
The Bitap Algorithm is an approximate string matching algorithm. The algorithm tells whether a given text contains a substring which is "approximately equal" to a given pattern. Here approximately equal states that if the substring and pattern are within a given distance k of each other. The algorit
5 min read
Java Program to Implement Wagner and Fisher Algorithm for Online String Matching
The Wagner-Fischer Algorithm is a dynamic programming algorithm that measures the Levenshtein distance or the edit distance between two strings of characters. Levenshtein Distance(LD) calculates how similar are the two strings. The distance is calculated by three parameters to transform the string1
3 min read
Java Program to Implement the String Search Algorithm for Short Text Sizes
Pattern searching is a crucial problem in computer science. When we do search for a string in notepad/word file or browser or database, pattern searching algorithms are used to show the search results. A typical problem statement would be-Given a text txt[0..n-1] and a pattern pat[0..m-1], write a f
4 min read
Implementing Rabin Karp Algorithm Using Rolling Hash in Java
There are so many pattern searching algorithms for the string. KMP algorithm, Z algorithm Rabin Karp algorithm, etc these algorithms are the optimization of Naive Pattern searching Algorithm. Naive Pattern Searching Algorithm: Input : "AABACACAACAC" Pattern : "CAC" Output : [4,9] AABACACAACAC Implem
5 min read
Java Program To Check Whether Two Strings Are Anagram
Write a function to check whether two given strings are anagrams of each other or not. An anagram of a string is another string that contains the same characters, only the order of characters can be different. For example, "abcd" and "dabc" are an anagram of each other. Program to Check Two Strings
8 min read
Java Program to Implement Levenshtein Distance Computing Algorithm
The Levenshtein distance also called the Edit distance, is the minimum number of operations required to transform one string to another. Typically, three types of operations are performed (one at a time) : Replace a character.Delete a character.Insert a character. Examples: Input: str1 = "glomax", s
6 min read
Java Program for KMP Algorithm for Pattern Searching
Given a text txt[0..n-1] and a pattern pat[0..m-1], write a function search(char pat[], char txt[]) that prints all occurrences of pat[] in txt[]. You may assume that n > m. Examples: Input: txt[] = "THIS IS A TEST TEXT" pat[] = "TEST" Output: Pattern found at index 10 Input: txt[] = "AABAACAADAA
3 min read
Java Program for Rabin-Karp Algorithm for Pattern Searching
Given a text txt[0..n-1] and a pattern pat[0..m-1], write a function search(char pat[], char txt[]) that prints all occurrences of pat[] in txt[]. You may assume that n > m. Examples: Input: txt[] = "THIS IS A TEST TEXT" pat[] = "TEST" Output: Pattern found at index 10 Input: txt[] = "AABAACAADAA
3 min read
Java Program for Naive algorithm for Pattern Searching
Write a Java program for a given text string with length n and a pattern with length m, the task is to print all occurrences of the pattern in text.Note: You may assume that n > m. Examples: Input: text = âTHIS IS A TEST TEXTâ, pattern = âTESTâOutput: Pattern found at index 10 Input: text = âAABA
2 min read
Java Program to Check Strings Anagram Using HashMap
Java Program to check whether two given strings are anagrams of each other or not using HashMap. What is an Anagram?A string is an anagram of another string if it contains the same characters in the same or in different order. Example of Anagram in JavaInput: s1 = "abcd" s2 = "cadb"Output: Two Strin
3 min read