Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
26828a7
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 27, 2024
4b09fab
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 27, 2024
713bc59
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 27, 2024
d2f326f
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 27, 2024
050cd02
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 28, 2024
7c622d9
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 28, 2024
6f078b2
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 28, 2024
4bfc268
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 28, 2024
5054426
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 28, 2024
5cd7c6e
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 28, 2024
e563fb4
add: initial implementation of Rabin-Karp algorithm for string matching
Lohit-pro Aug 28, 2024
3ff0c7c
Merge branch 'master' into Rabin-Karp-Algo
Lohit-pro Aug 28, 2024
af911b1
Merge branch 'master' into Rabin-Karp-Algo
Lohit-pro Sep 16, 2024
41ea5c1
test: PatternSearchUsingRabinKarpAlgoTest
Lohit-pro Sep 16, 2024
574f45a
Merge remote-tracking branch 'origin/Rabin-Karp-Algo' into Rabin-Karp…
Lohit-pro Sep 16, 2024
e8248d4
test: PatternSearchUsingRabinKarpAlgoTest
Lohit-pro Sep 16, 2024
7330323
test: PatternSearchUsingRabinKarpAlgoTest
Lohit-pro Sep 16, 2024
1f73373
test: PatternSearchUsingRabinKarpAlgoTest
Lohit-pro Sep 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pmd-exclude.properties
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,4 @@ com.thealgorithms.strings.HorspoolSearch=UnnecessaryFullyQualifiedName,UselessPa
com.thealgorithms.strings.MyAtoi=UselessParentheses
com.thealgorithms.strings.Palindrome=UselessParentheses
com.thealgorithms.strings.Solution=CollapsibleIfStatements
com.thealgorithms.strings.PatternSearchUsingRabinKarpAlgo.java=UselessParentheses
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.thealgorithms.strings;
import java.util.ArrayList;
import java.util.List;

/*
@author Lohit M Kudlannavar (https://github.com/Lohit-pro)

https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
The Rabin-Karp algorithm calculates a hash value for the pattern and a hash value for a sliding window
of text in the same length as the pattern. If the hash values match, it checks character by character
to confirm that it's an exact match.
*/

public final class PatternSearchUsingRabinKarpAlgo {

private PatternSearchUsingRabinKarpAlgo() {
}

// I'm using Rabin-Karp algorithm that uses hashing to find pattern strings in a text.
public static List<String> search(String text, String pattern) {
List<String> result = new ArrayList<>();
text = text.toLowerCase();
pattern = pattern.toLowerCase();
int m = pattern.length();
int n = text.length();
int prime = 101; // A prime number to mod hash values

int patternHash = 0; // Hash value for pattern
int textHash = 0; // Hash value for text window
int h = 1;

// The value of h would be "pow(d, m-1) % prime"
for (int i = 0; i < m - 1; i++) {
h = h * 256 % prime;
}

// Calculating the hash value of pattern and first window of text
for (int i = 0; i < m; i++) {
patternHash = (256 * patternHash + pattern.charAt(i)) % prime;
textHash = (256 * textHash + text.charAt(i)) % prime;
}

// Iterating on pattern by single char again and again..
for (int i = 0; i <= n - m; i++) {

if (patternHash == textHash) {
// If the hash values match, then only checking for next char's
int j;
for (j = 0; j < m; j++) {
if (text.charAt(i + j) != pattern.charAt(j)) {
break;
}
}

// If patternHash == textHash and pattern[0...m-1] == text[i...i+m-1]
if (j == m) {
result.add("Start: " + i + ", End: " + (i + m - 1) + ", Substring: " + text.substring(i, i + m));
}
}

// Calculating hash value for next window of text: Remove leading digit, add trailing digit
if (i < n - m) {
textHash = (256 * (textHash - text.charAt(i) * h) + text.charAt(i + m)) % prime;

// We might get negative value of textHash,so converting it to positive
if (textHash < 0) {
textHash = (textHash + prime);
}
}
}

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.thealgorithms.strings;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import org.junit.jupiter.api.Test;

public class PatternSearchUsingRabinKarpAlgoTest {

@Test
public void testPatternFoundInMiddle() {
String text = "ABCCDDAEFG";
String pattern = "CDD";
List<String> result = PatternSearchUsingRabinKarpAlgo.search(text, pattern);
assertFalse(result.isEmpty(), "Pattern should be found");
assertEquals("Start: 3, End: 5, Substring: cdd", result.get(0));
}

@Test
public void testPatternAtStart() {
String text = "ABCCDDAEFG";
String pattern = "AB";
List<String> result = PatternSearchUsingRabinKarpAlgo.search(text, pattern);
assertFalse(result.isEmpty(), "Pattern should be found");
assertEquals("Start: 0, End: 1, Substring: ab", result.get(0));
}

@Test
public void testPatternAtEnd() {
String text = "ABCCDDAEFG";
String pattern = "EFG";
List<String> result = PatternSearchUsingRabinKarpAlgo.search(text, pattern);
assertFalse(result.isEmpty(), "Pattern should be found");
assertEquals("Start: 7, End: 9, Substring: efg", result.get(0));
}

@Test
public void testPatternNotFound() {
String text = "ABCCDDAEFG";
String pattern = "XYZ";
List<String> result = PatternSearchUsingRabinKarpAlgo.search(text, pattern);
assertTrue(result.isEmpty(), "Pattern should not be found");
}

@Test
public void testPatternEqualsText() {
String text = "ABCCDDAEFG";
String pattern = "ABCCDDAEFG";
List<String> result = PatternSearchUsingRabinKarpAlgo.search(text, pattern);
assertFalse(result.isEmpty(), "Pattern should match entire text");
assertEquals("Start: 0, End: 9, Substring: abccddaefg", result.get(0));
}

@Test
public void testMultipleMatches() {
String text = "AAAAAA";
String pattern = "AA";
List<String> result = PatternSearchUsingRabinKarpAlgo.search(text, pattern);
assertEquals(5, result.size(), "Pattern should appear multiple times");
}

@Test
public void testCaseInsensitiveSearch() {
String text = "HelloWorld";
String pattern = "helloworld";
List<String> result = PatternSearchUsingRabinKarpAlgo.search(text, pattern);
assertFalse(result.isEmpty(), "Pattern should match regardless of case");
assertEquals("Start: 0, End: 9, Substring: helloworld", result.get(0));
}
}