From f2a5c1e9ac12a46dbbbdecb854b71d4f4099a754 Mon Sep 17 00:00:00 2001 From: Divyansh Saxena Date: Sat, 31 Jan 2026 01:31:52 +0530 Subject: [PATCH 1/2] first commit --- .../java/com/thealgorithms/strings/KMP.java | 27 +++++++---- .../com/thealgorithms/strings/RabinKarp.java | 47 ++++++------------- .../com/thealgorithms/strings/KMPTest.java | 21 +++++++++ .../thealgorithms/strings/RabinKarpTest.java | 21 +++++++++ 4 files changed, 74 insertions(+), 42 deletions(-) create mode 100644 src/test/java/com/thealgorithms/strings/KMPTest.java create mode 100644 src/test/java/com/thealgorithms/strings/RabinKarpTest.java diff --git a/src/main/java/com/thealgorithms/strings/KMP.java b/src/main/java/com/thealgorithms/strings/KMP.java index 07d3b0415006..0317abe6f39a 100644 --- a/src/main/java/com/thealgorithms/strings/KMP.java +++ b/src/main/java/com/thealgorithms/strings/KMP.java @@ -1,5 +1,8 @@ package com.thealgorithms.strings; +import java.util.ArrayList; +import java.util.List; + /** * Implementation of Knuth–Morris–Pratt algorithm Usage: see the main function * for an example @@ -8,16 +11,19 @@ public final class KMP { private KMP() { } - // a working example - - public static void main(String[] args) { - final String haystack = "AAAAABAAABA"; // This is the full string - final String needle = "AAAA"; // This is the substring that we want to find - kmpMatcher(haystack, needle); - } + /** + * find the starting index in string haystack[] that matches the search word P[] + * + * @param haystack The text to be searched + * @param needle The pattern to be searched for + * @return A list of starting indices where the pattern is found + */ + public static List kmpMatcher(final String haystack, final String needle) { + List occurrences = new ArrayList<>(); + if (haystack == null || needle == null || needle.isEmpty()) { + return occurrences; + } - // find the starting index in string haystack[] that matches the search word P[] - public static void kmpMatcher(final String haystack, final String needle) { final int m = haystack.length(); final int n = needle.length(); final int[] pi = computePrefixFunction(needle); @@ -32,10 +38,11 @@ public static void kmpMatcher(final String haystack, final String needle) { } if (q == n) { - System.out.println("Pattern starts: " + (i + 1 - n)); + occurrences.add(i + 1 - n); q = pi[q - 1]; } } + return occurrences; } // return the prefix function diff --git a/src/main/java/com/thealgorithms/strings/RabinKarp.java b/src/main/java/com/thealgorithms/strings/RabinKarp.java index bb8df3358453..e0f63ed757f3 100644 --- a/src/main/java/com/thealgorithms/strings/RabinKarp.java +++ b/src/main/java/com/thealgorithms/strings/RabinKarp.java @@ -1,32 +1,30 @@ package com.thealgorithms.strings; -import java.util.Scanner; +import java.util.ArrayList; +import java.util.List; /** * @author Prateek Kumar Oraon (https://github.com/prateekKrOraon) * - An implementation of Rabin-Karp string matching algorithm - Program will simply end if there is no match + * An implementation of Rabin-Karp string matching algorithm + * Program will simply end if there is no match */ public final class RabinKarp { private RabinKarp() { } - public static Scanner scanner = null; - public static final int ALPHABET_SIZE = 256; + private static final int ALPHABET_SIZE = 256; - public static void main(String[] args) { - scanner = new Scanner(System.in); - System.out.println("Enter String"); - String text = scanner.nextLine(); - System.out.println("Enter pattern"); - String pattern = scanner.nextLine(); - - int q = 101; - searchPat(text, pattern, q); + public static List search(String text, String pattern) { + return search(text, pattern, 101); } - private static void searchPat(String text, String pattern, int q) { + public static List search(String text, String pattern, int q) { + List occurrences = new ArrayList<>(); + if (text == null || pattern == null || pattern.isEmpty()) { + return occurrences; + } + int m = pattern.length(); int n = text.length(); int t = 0; @@ -38,45 +36,30 @@ private static void searchPat(String text, String pattern, int q) { h = (int) Math.pow(ALPHABET_SIZE, m - 1) % q; for (i = 0; i < m; i++) { - // hash value is calculated for each character and then added with the hash value of the - // next character for pattern as well as the text for length equal to the length of - // pattern p = (ALPHABET_SIZE * p + pattern.charAt(i)) % q; t = (ALPHABET_SIZE * t + text.charAt(i)) % q; } for (i = 0; i <= n - m; i++) { - // if the calculated hash value of the pattern and text matches then - // all the characters of the pattern is matched with the text of length equal to length - // of the pattern if all matches then pattern exist in string if not then the hash value - // of the first character of the text is subtracted and hash value of the next character - // after the end of the evaluated characters is added if (p == t) { - // if hash value matches then the individual characters are matched for (j = 0; j < m; j++) { - // if not matched then break out of the loop if (text.charAt(i + j) != pattern.charAt(j)) { break; } } - // if all characters are matched then pattern exist in the string if (j == m) { - System.out.println("Pattern found at index " + i); + occurrences.add(i); } } - // if i Date: Sat, 31 Jan 2026 01:56:21 +0530 Subject: [PATCH 2/2] Running KMPTest and RabinKarpTest with fixed formatting --- .../java/com/thealgorithms/strings/RabinKarp.java | 15 ++++++++++++--- .../java/com/thealgorithms/strings/KMPTest.java | 3 ++- .../com/thealgorithms/strings/RabinKarpTest.java | 3 ++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/RabinKarp.java b/src/main/java/com/thealgorithms/strings/RabinKarp.java index e0f63ed757f3..b4d7a92dfb65 100644 --- a/src/main/java/com/thealgorithms/strings/RabinKarp.java +++ b/src/main/java/com/thealgorithms/strings/RabinKarp.java @@ -33,7 +33,14 @@ public static List search(String text, String pattern, int q) { int j = 0; int i = 0; - h = (int) Math.pow(ALPHABET_SIZE, m - 1) % q; + if (m > n) { + return new ArrayList<>(); + } + + // h = pow(ALPHABET_SIZE, m-1) % q + for (i = 0; i < m - 1; i++) { + h = (h * ALPHABET_SIZE) % q; + } for (i = 0; i < m; i++) { p = (ALPHABET_SIZE * p + pattern.charAt(i)) % q; @@ -54,10 +61,12 @@ public static List search(String text, String pattern, int q) { } if (i < n - m) { - t = (ALPHABET_SIZE * (t - text.charAt(i) * h) + text.charAt(i + m)) % q; + t = (t - (text.charAt(i) * h) % q); if (t < 0) { - t = (t + q); + t += q; } + t = (t * ALPHABET_SIZE) % q; + t = (t + text.charAt(i + m)) % q; } } return occurrences; diff --git a/src/test/java/com/thealgorithms/strings/KMPTest.java b/src/test/java/com/thealgorithms/strings/KMPTest.java index 92b026df8767..852c3848804b 100644 --- a/src/test/java/com/thealgorithms/strings/KMPTest.java +++ b/src/test/java/com/thealgorithms/strings/KMPTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.strings; import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.List; import org.junit.jupiter.api.Test; @@ -9,7 +10,7 @@ public class KMPTest { @Test public void testKMPMatcher() { assertEquals(List.of(0, 1), KMP.kmpMatcher("AAAAABAAABA", "AAAA")); - assertEquals(List.of(0, 2), KMP.kmpMatcher("ABCABC", "ABC")); + assertEquals(List.of(0, 3), KMP.kmpMatcher("ABCABC", "ABC")); assertEquals(List.of(10), KMP.kmpMatcher("ABABDABACDABABCABAB", "ABABCABAB")); assertEquals(List.of(), KMP.kmpMatcher("ABCDE", "FGH")); assertEquals(List.of(), KMP.kmpMatcher("A", "AA")); diff --git a/src/test/java/com/thealgorithms/strings/RabinKarpTest.java b/src/test/java/com/thealgorithms/strings/RabinKarpTest.java index 993d289fa924..358c544672b0 100644 --- a/src/test/java/com/thealgorithms/strings/RabinKarpTest.java +++ b/src/test/java/com/thealgorithms/strings/RabinKarpTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.strings; import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.List; import org.junit.jupiter.api.Test; @@ -9,7 +10,7 @@ public class RabinKarpTest { @Test public void testRabinKarpSearch() { assertEquals(List.of(0, 1), RabinKarp.search("AAAAABAAABA", "AAAA")); - assertEquals(List.of(0, 2), RabinKarp.search("ABCABC", "ABC")); + assertEquals(List.of(0, 3), RabinKarp.search("ABCABC", "ABC")); assertEquals(List.of(10), RabinKarp.search("ABABDABACDABABCABAB", "ABABCABAB")); assertEquals(List.of(), RabinKarp.search("ABCDE", "FGH")); assertEquals(List.of(), RabinKarp.search("A", "AA"));