Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 11 additions & 7 deletions src/main/java/com/thealgorithms/strings/HorspoolSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public static Integer getLastComparisons() {
* @return index of first occurrence of the pattern in the text
*/
private static int firstOccurrence(String pattern, String text, boolean caseSensitive) {
shiftValues = calcShiftValues(pattern); // build the bad symbol table
shiftValues = calcShiftValues(pattern, caseSensitive); // build the bad symbol table
comparisons = 0; // reset comparisons

if (pattern.length() == 0) { // return failure, if pattern empty
Expand All @@ -113,7 +113,7 @@ private static int firstOccurrence(String pattern, String text, boolean caseSens
char patternChar = pattern.charAt(i);
char textChar = text.charAt((textIndex + i) - (pattern.length() - 1));
if (!charEquals(patternChar, textChar, caseSensitive)) { // bad character, shift pattern
textIndex += getShiftValue(text.charAt(textIndex));
textIndex += getShiftValue(text.charAt(textIndex), caseSensitive);
break;
}
i--;
Expand Down Expand Up @@ -153,14 +153,15 @@ private static boolean charEquals(char c1, char c2, boolean caseSensitive) {
* in the table, then it is not a rightmost occurrence, so it continues.
*
* @param pattern basis for the bad symbol table
* @param caseSensitive whether to build the table with case-sensitive keys
* @return the bad symbol table
*/
private static HashMap<Character, Integer> calcShiftValues(String pattern) {
private static HashMap<Character, Integer> calcShiftValues(String pattern, boolean caseSensitive) {
patternLength = pattern.length();
HashMap<Character, Integer> table = new HashMap<>();

for (int i = pattern.length() - 2; i >= 0; i--) { // length - 2 is the index of the second to last character
char c = pattern.charAt(i);
char c = caseSensitive ? pattern.charAt(i) : Character.toLowerCase(pattern.charAt(i));
int finalI = i;
table.computeIfAbsent(c, k -> pattern.length() - 1 - finalI);
}
Expand All @@ -173,11 +174,14 @@ private static HashMap<Character, Integer> calcShiftValues(String pattern) {
* appropriate shift value for a given character
*
* @param c character
* @param caseSensitive whether the table was built with case-sensitive keys
* @return shift value that corresponds to the character argument
*/
private static Integer getShiftValue(char c) {
if (shiftValues.get(c) != null) {
return shiftValues.get(c);
private static Integer getShiftValue(char c, boolean caseSensitive) {
// the table holds lower-case keys for case-insensitive searches
char key = caseSensitive ? c : Character.toLowerCase(c);
if (shiftValues.get(key) != null) {
return shiftValues.get(key);
} else {
return patternLength;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ void testFindFirstInsensitiveNotMatch() {
assertEquals(-1, index);
}

@Test
void testFindFirstInsensitiveWhenCaseDiffersFromPattern() {
assertEquals(1, HorspoolSearch.findFirstInsensitive("AB", "xab"));
assertEquals(1, HorspoolSearch.findFirstInsensitive("ab", "xAB"));
assertEquals(2, HorspoolSearch.findFirstInsensitive("ba", "bbBA"));
}

@Test
void testGetLastComparisons() {
HorspoolSearch.findFirst("World", "Hello World");
Expand Down
Loading