From 78a9c4004697c86b88e64668c560072e75bf68dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 17:52:30 +0200 Subject: [PATCH 1/9] Add Boyer-Moore string search algorithm --- .../thealgorithms/searches/BoyerMoore.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/thealgorithms/searches/BoyerMoore.java diff --git a/src/main/java/com/thealgorithms/searches/BoyerMoore.java b/src/main/java/com/thealgorithms/searches/BoyerMoore.java new file mode 100644 index 000000000000..cd25cb3fe133 --- /dev/null +++ b/src/main/java/com/thealgorithms/searches/BoyerMoore.java @@ -0,0 +1,48 @@ +package com.thealgorithms.searches; + +/** + * Boyer-Moore string search algorithm + * Efficient algorithm for substring search. + * + * @author Pau +*/ + +public class BoyerMoore { + + private final int R; + private int[] right; + private String pattern; + + public BoyerMoore(String pat) { + this.pattern = pat; + this.R = 256; + this.right = new int[R]; + for (int c = 0; c < R; c++) + right[c] = -1; + for (int j = 0; j < pat.length(); j++) + right[pat.charAt(j)] = j; + } + + public int search(String text) { + int m = pattern.length(); + int n = text.length(); + int skip; + + for (int i = 0; i <= n - m; i += skip) { + skip = 0; + for (int j = m - 1; j >= 0; j--) { + if (pattern.charAt(j) != text.charAt(i + j)) { + skip = Math.max(1, j - right[text.charAt(i + j)]); + break; + } + } + if (skip == 0) + return i; + } + return -1; + } + + public static int search(String text, String pattern) { + return new BoyerMoore(pattern).search(text); + } +} From 12cf5be807a790a80fb0c4fa53d911986f43ce81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 17:53:50 +0200 Subject: [PATCH 2/9] Add Boyer-Moore JUnit tests --- BoyerMooreTest.java | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 BoyerMooreTest.java diff --git a/BoyerMooreTest.java b/BoyerMooreTest.java new file mode 100644 index 000000000000..6edb70d71062 --- /dev/null +++ b/BoyerMooreTest.java @@ -0,0 +1,55 @@ +package com.thealgorithms.searches; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +public class BoyerMooreTest { + + @Test + public void testPatternFound() { + BoyerMoore bm = new BoyerMoore("ABCDABD"); + String text = "ABC ABCDAB ABCDABCDABDE"; + int index = bm.search(text); + assertEquals(15, index); + } + + @Test + public void testPatternNotFound() { + BoyerMoore bm = new BoyerMoore("XYZ"); + String text = "ABC ABCDAB ABCDABCDABDE"; + int index = bm.search(text); + assertEquals(-1, index); + } + + @Test + public void testPatternAtBeginning() { + BoyerMoore bm = new BoyerMoore("ABC"); + String text = "ABCDEF"; + int index = bm.search(text); + assertEquals(0, index); + } + + @Test + public void testPatternAtEnd() { + BoyerMoore bm = new BoyerMoore("CDE"); + String text = "ABCDEFGCDE"; + int index = bm.search(text); + assertEquals(2, index); + } + + + @Test + public void testEmptyPattern() { + BoyerMoore bm = new BoyerMoore(""); + String text = "Hello world"; + int index = bm.search(text); + assertEquals(0, index); + } + + @Test + public void testStaticSearchMethod() { + int index = BoyerMoore.search("ABCDEFGCDE", "CDE"); + assertEquals(2, index); + } + +} From 4553e6813f63267ce9530301ab4bde08d97479de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 17:57:44 +0200 Subject: [PATCH 3/9] Delete BoyerMooreTest.java --- BoyerMooreTest.java | 55 --------------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 BoyerMooreTest.java diff --git a/BoyerMooreTest.java b/BoyerMooreTest.java deleted file mode 100644 index 6edb70d71062..000000000000 --- a/BoyerMooreTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.thealgorithms.searches; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - -public class BoyerMooreTest { - - @Test - public void testPatternFound() { - BoyerMoore bm = new BoyerMoore("ABCDABD"); - String text = "ABC ABCDAB ABCDABCDABDE"; - int index = bm.search(text); - assertEquals(15, index); - } - - @Test - public void testPatternNotFound() { - BoyerMoore bm = new BoyerMoore("XYZ"); - String text = "ABC ABCDAB ABCDABCDABDE"; - int index = bm.search(text); - assertEquals(-1, index); - } - - @Test - public void testPatternAtBeginning() { - BoyerMoore bm = new BoyerMoore("ABC"); - String text = "ABCDEF"; - int index = bm.search(text); - assertEquals(0, index); - } - - @Test - public void testPatternAtEnd() { - BoyerMoore bm = new BoyerMoore("CDE"); - String text = "ABCDEFGCDE"; - int index = bm.search(text); - assertEquals(2, index); - } - - - @Test - public void testEmptyPattern() { - BoyerMoore bm = new BoyerMoore(""); - String text = "Hello world"; - int index = bm.search(text); - assertEquals(0, index); - } - - @Test - public void testStaticSearchMethod() { - int index = BoyerMoore.search("ABCDEFGCDE", "CDE"); - assertEquals(2, index); - } - -} From b20e5c09a340a77ff40d61631ed38e9af7ea5944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 18:00:19 +0200 Subject: [PATCH 4/9] Add JUnit test BoyerMooreTest.java --- .../searches/BoyerMooreTest.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/test/java/com/thealgorithms/searches/BoyerMooreTest.java diff --git a/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java b/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java new file mode 100644 index 000000000000..6edb70d71062 --- /dev/null +++ b/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java @@ -0,0 +1,55 @@ +package com.thealgorithms.searches; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +public class BoyerMooreTest { + + @Test + public void testPatternFound() { + BoyerMoore bm = new BoyerMoore("ABCDABD"); + String text = "ABC ABCDAB ABCDABCDABDE"; + int index = bm.search(text); + assertEquals(15, index); + } + + @Test + public void testPatternNotFound() { + BoyerMoore bm = new BoyerMoore("XYZ"); + String text = "ABC ABCDAB ABCDABCDABDE"; + int index = bm.search(text); + assertEquals(-1, index); + } + + @Test + public void testPatternAtBeginning() { + BoyerMoore bm = new BoyerMoore("ABC"); + String text = "ABCDEF"; + int index = bm.search(text); + assertEquals(0, index); + } + + @Test + public void testPatternAtEnd() { + BoyerMoore bm = new BoyerMoore("CDE"); + String text = "ABCDEFGCDE"; + int index = bm.search(text); + assertEquals(2, index); + } + + + @Test + public void testEmptyPattern() { + BoyerMoore bm = new BoyerMoore(""); + String text = "Hello world"; + int index = bm.search(text); + assertEquals(0, index); + } + + @Test + public void testStaticSearchMethod() { + int index = BoyerMoore.search("ABCDEFGCDE", "CDE"); + assertEquals(2, index); + } + +} From 807e668f8174339732f81e76f56caaa23a9c266a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 18:04:20 +0200 Subject: [PATCH 5/9] Add Wiki link BoyerMoore.java --- src/main/java/com/thealgorithms/searches/BoyerMoore.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/searches/BoyerMoore.java b/src/main/java/com/thealgorithms/searches/BoyerMoore.java index cd25cb3fe133..895255121669 100644 --- a/src/main/java/com/thealgorithms/searches/BoyerMoore.java +++ b/src/main/java/com/thealgorithms/searches/BoyerMoore.java @@ -1,11 +1,11 @@ package com.thealgorithms.searches; - /** * Boyer-Moore string search algorithm * Efficient algorithm for substring search. * - * @author Pau -*/ + * @see + * https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm + */ public class BoyerMoore { From a685d22d02e1334a7545d247538cd135b1dfc0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 18:11:43 +0200 Subject: [PATCH 6/9] Add Clang format BoyerMoore.java --- .../com/thealgorithms/searches/BoyerMoore.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/thealgorithms/searches/BoyerMoore.java b/src/main/java/com/thealgorithms/searches/BoyerMoore.java index 895255121669..1a03b6817ae9 100644 --- a/src/main/java/com/thealgorithms/searches/BoyerMoore.java +++ b/src/main/java/com/thealgorithms/searches/BoyerMoore.java @@ -1,12 +1,10 @@ package com.thealgorithms.searches; + /** * Boyer-Moore string search algorithm * Efficient algorithm for substring search. - * - * @see - * https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm + * https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search-algorithm */ - public class BoyerMoore { private final int R; @@ -17,10 +15,12 @@ public BoyerMoore(String pat) { this.pattern = pat; this.R = 256; this.right = new int[R]; - for (int c = 0; c < R; c++) + for (int c = 0; c < R; c++) { right[c] = -1; - for (int j = 0; j < pat.length(); j++) + } + for (int j = 0; j < pat.length(); j++) { right[pat.charAt(j)] = j; + } } public int search(String text) { @@ -36,8 +36,9 @@ public int search(String text) { break; } } - if (skip == 0) + if (skip == 0) { return i; + } } return -1; } From 83f7eeaaaaeebcbd3b0dcc373672cebc93039173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 18:12:28 +0200 Subject: [PATCH 7/9] Add Clang format BoyerMooreTest.java --- .../com/thealgorithms/searches/BoyerMooreTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java b/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java index 6edb70d71062..8c69ce93026d 100644 --- a/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java +++ b/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.searches; import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; public class BoyerMooreTest { @@ -34,22 +35,21 @@ public void testPatternAtEnd() { BoyerMoore bm = new BoyerMoore("CDE"); String text = "ABCDEFGCDE"; int index = bm.search(text); - assertEquals(2, index); - } - + assertEquals(7, index); + } @Test public void testEmptyPattern() { BoyerMoore bm = new BoyerMoore(""); String text = "Hello world"; int index = bm.search(text); - assertEquals(0, index); + assertEquals(0, index); } @Test public void testStaticSearchMethod() { - int index = BoyerMoore.search("ABCDEFGCDE", "CDE"); - assertEquals(2, index); + String text = "ABCDEFGCDE"; + int index = BoyerMoore.search(text, "CDE"); + assertEquals(7, index); } - } From 3734afad146c9acbde7ed8d3a11b81a9c54eb8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 18:18:29 +0200 Subject: [PATCH 8/9] Update BoyerMoore.java --- .../thealgorithms/searches/BoyerMoore.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/thealgorithms/searches/BoyerMoore.java b/src/main/java/com/thealgorithms/searches/BoyerMoore.java index 1a03b6817ae9..92a7d9388539 100644 --- a/src/main/java/com/thealgorithms/searches/BoyerMoore.java +++ b/src/main/java/com/thealgorithms/searches/BoyerMoore.java @@ -1,9 +1,7 @@ -package com.thealgorithms.searches; - /** * Boyer-Moore string search algorithm * Efficient algorithm for substring search. - * https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search-algorithm + * https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm */ public class BoyerMoore { @@ -13,34 +11,40 @@ public class BoyerMoore { public BoyerMoore(String pat) { this.pattern = pat; - this.R = 256; + this.R = 256; // extended ASCII this.right = new int[R]; + + // Initialize all occurrences as -1 for (int c = 0; c < R; c++) { right[c] = -1; } + + // Fill the actual value of last occurrence of a character for (int j = 0; j < pat.length(); j++) { right[pat.charAt(j)] = j; } } public int search(String text) { + if (pattern.isEmpty()) return 0; + int m = pattern.length(); int n = text.length(); - int skip; + int skip; for (int i = 0; i <= n - m; i += skip) { skip = 0; for (int j = m - 1; j >= 0; j--) { - if (pattern.charAt(j) != text.charAt(i + j)) { - skip = Math.max(1, j - right[text.charAt(i + j)]); + char txtChar = text.charAt(i + j); + char patChar = pattern.charAt(j); + if (patChar != txtChar) { + skip = Math.max(1, j - right[txtChar]); break; } } - if (skip == 0) { - return i; - } + if (skip == 0) return i; // found } - return -1; + return -1; // not found } public static int search(String text, String pattern) { From d5033595f8eaab811f00e4165ddcb422040e31cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20L=C3=B3pez=20N=C3=BA=C3=B1ez?= Date: Sun, 8 Jun 2025 18:23:47 +0200 Subject: [PATCH 9/9] Update BoyerMooreTest.java --- src/test/java/com/thealgorithms/searches/BoyerMooreTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java b/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java index 8c69ce93026d..0a4414bf9ed8 100644 --- a/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java +++ b/src/test/java/com/thealgorithms/searches/BoyerMooreTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import com.thealgorithms.searches.BoyerMoore; public class BoyerMooreTest {