75 lines
2.6 KiB
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;
|
|
}
|
|
}
|