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; } }