import java.util.*;
import java.util.stream.*;
import java.util.concurrent.*;
class Main {
public static void main(String[] args) {
FED fed = new FED ();
fed.add("傻逼", "FK", "脑残");
System.out.println(fed.getDict());
System.out.println(fed.check("我不和傻逼玩,万一也脑残就不好了~"));
}
public static class FED {
private boolean[] first = new boolean[Character.MAX_VALUE];
private boolean[] end = new boolean[Character.MAX_VALUE];
private int maxLength;
private final Map<Integer, Set<String>> wordDict = new ConcurrentHashMap<>(1024);
public Set<Word> check (String text) {
Set<Word> result = new HashSet<>();
if (isNotBlank(text)) {
int len = text.length();
int[] start = new int[maxLength];
int firstCount = 0,
oldestOffset = 0;
for (int i = 0; i < len; i++) {
char c = text.charAt(i);
if (first[c]) {
oldestOffset = firstCount < maxLength ? 0 : (1 + (firstCount % maxLength)) % maxLength;
start[firstCount++ % maxLength] = i;
}
if (firstCount > 0 && end[c]) {
int hash = 0, offsetFirst = firstCount - 1;
for (int j = i + 1; --j >= start[oldestOffset]; ) {
hash = hash (hash, text.charAt(j));
if (j == start[offsetFirst % maxLength]) {
--offsetFirst;
if (wordDict.containsKey(hash)) {
String word = text.substring(j, i + 1);
if (wordDict.get(hash).contains(word)) {
result.add(Word.of(word, j));
break;
}
}
}
}
}
}
}
return result;
}
public void add (String... words) {
if (words != null && words.length > 0) {
Arrays.asList(words).stream().filter(Objects::nonNull).collect(Collectors.toSet()).stream().forEach(this::add);
}
}
public Map<Integer, Set<String>> getDict () {
return this.wordDict;
}
private void add (String pattern) {
assert isNotBlank(pattern);
int len = pattern.length();
first[pattern.charAt(0)] = true;
end[pattern.charAt(len - 1)] = true;
if (len > maxLength) {
maxLength = len;
}
int hash = 0;
for (int i = len; --i >= 0;) {
hash = hash(hash, pattern.charAt(i));
}
wordDict.computeIfAbsent(hash, k -> new HashSet<>()).add(pattern);
}
private int hash (int hash, Character c) {
return 31 * hash + c;
}
private boolean isNotBlank (String str) {
return str != null && str.trim().length() > 0;
}
}
public static class Word {
private int index;
private String key;
public static Word of (String key, int index) {
assert key != null && index >= 0;
Word word = new Word();
word.index = index;
word.key = key;
return word;
}
public int getIndex () { return index; }
public String getKey () { return key; }
public String toString () {
return "{\"key\":\"" + key + "\", \"index\":" + index + "}";
}
}
}