package com.formulasearchengine.mathosphere.mathpd.text; /** * Found as an example but modified it to be better usable. * * @author Vincent Stange */ public class BoyerMooreSearch { private static final int ALPHABET_SIZE = 64000; /* Initialize this array only once */ private int[] charTable = new int[ALPHABET_SIZE]; public int search(char[] pattern, char[] text, int startIdx, int endIdx) { int[] charTable = makeCharTable(pattern); int[] offsetTable = makeOffsetTable(pattern); // evaluate the end index, maximum is the end of the text endIdx = endIdx != 0 ? Math.min(endIdx, text.length) : text.length; for (int i = pattern.length + startIdx - 1, j; i < endIdx; ) { for (j = pattern.length - 1; pattern[j] == text[i]; i--, j--) { if (j == 0) { return i; } } i += Math.max(charTable[text[i]], offsetTable[pattern.length - j - 1]); } return -1; } private int[] makeCharTable(char[] pattern) { for (int i = 0; i < charTable.length; i++) { charTable[i] = pattern.length; } for (int i = 0; i < pattern.length - 1; i++) { charTable[pattern[i]] = pattern.length - i - 1; } return charTable; } private static int[] makeOffsetTable(char[] pattern) { int[] offsetTable = new int[pattern.length]; int lastPrefixPosition = pattern.length; for (int i = pattern.length - 1; i >= 0; --i) { if (isPrefix(pattern, i + 1)) { lastPrefixPosition = i + 1; } offsetTable[pattern.length - i - 1] = lastPrefixPosition - i + pattern.length - 1; } for (int i = 0; i < pattern.length - 1; i++) { int suffixLen = suffixLength(pattern, i); offsetTable[suffixLen] = pattern.length - i - 1 + suffixLen; } return offsetTable; } private static boolean isPrefix(char[] pattern, int p) { for (int i = p, j = 0; i < pattern.length; i++, j++) { if (pattern[i] != pattern[j]) { return false; } } return true; } private static int suffixLength(char[] pattern, int p) { int len = 0; for (int i = p, j = pattern.length - 1; i >= 0 && pattern[i] == pattern[j]; --i, --j) { len += 1; } return len; } }