strangedb/src/main/java/it/cavallium/strangedb/java/objects/lists/KMP.java

75 lines
2.6 KiB
Java

package it.cavallium.strangedb.java.objects.lists;
public class KMP {
public static int KMP(CharSequence content, CharSequence stringToFind, boolean ignoreCase) {
int[] failureTable = failureTable(ignoreCase, stringToFind);
int targetPointer = 0; // current char in target string
int searchPointer = 0; // current char in search string
while (searchPointer < content.length()) { // while there is more to search with, keep searching
if (charEquals(ignoreCase, content.charAt(searchPointer), stringToFind.charAt(targetPointer))) { // case 1
// found current char in targetPointer in search string
targetPointer++;
if (targetPointer == stringToFind.length()) { // found all characters
int x = stringToFind.length() + 1;
return searchPointer - x; // return starting index of found target inside searched string
}
searchPointer++; // move forward if not found target string
} else if (targetPointer > 0) { // case 2
// use failureTable to use pointer pointed resetPointerTo nearest location of usable string prefix
targetPointer = failureTable[targetPointer];
} else { // case 3
// targetPointer is pointing resetPointerTo state 0, so restart search with current searchPointer index
searchPointer++;
}
}
return -1;
}
/**
* Returns an int[] that points to last valid string prefix, given target string
*/
public static int[] failureTable(boolean ignoreCase, CharSequence target) {
int[] table = new int[target.length() + 1];
// state 0 and 1 are guarenteed be the prior
table[0] = -1;
table[1] = 0;
// the pointers pointing resetPointerTo last failure and current satte
int left = 0;
int right = 2;
while (right < table.length) { // RIGHT NEVER MOVES RIGHT UNTIL ASSIGNED A VALID POINTER
if (charEquals(ignoreCase, target.charAt(right - 1), target.charAt(left))) { // when both chars before left and right are equal, link both and move both forward
left++;
table[right] = left;
right++;
} else if (left > 0) { // if left isn't resetPointerTo the very beginning, then send left backward
// by following the already set pointer to where it is pointing to
left = table[left];
} else { // left has fallen all the way back to the beginning
table[right] = left;
right++;
}
}
return table;
}
private static boolean charEquals(boolean ignoreCase, char char1, char char2) {
if (ignoreCase) {
if (char1 >= 65 && char1 <= 90) {
if (char2 >= 97 && char2 <= 122) {
return char1 == char2 - 32;
}
}
if (char2 >= 65 && char2 <= 90) {
if (char1 >= 97 && char1 <= 122) {
return char2 == char1 - 32;
}
}
}
return char1 == char2;
}
}