@Nullable
    public String findUnwantedWords(String text, int maxNumberOfUnwantedWordsToReturn) {
        char code;
        Object newChars;
        int firstByteIndex = 0;
        int currentState = 0;
        int nextState;
        FastStringBuilder builder = null;
        int length = text.length();
        byte[] textInternalBytes = null;
        byte coder = StringUtil.getCoder(text);
        boolean isLatin1 = StringUtil.isLatin1(coder);
        for (int i = 0; i < length; i++) {
            code = text.charAt(i);
            newChars = textPreprocessor.process(code);
            if (currentState == ROOT_STATUS) {
                firstByteIndex = isLatin1
                        ? i
                        : i * 2;
            }
            if (newChars instanceof char[] chars) {
                for (char c : chars) {
                    nextState = transition(currentState, c);
                    while (nextState == STATUS_NOT_FOUND) {
                        currentState = fail[currentState];
                        if (currentState == ROOT_STATUS) {
                            firstByteIndex = isLatin1
                                    ? i
                                    : i * 2;
                        }
                        nextState = transition(currentState, c);
                    }
                    currentState = nextState;
                    if (output[currentState] != null) {
                        if (builder == null) {
                            builder = new FastStringBuilder();
                            textInternalBytes = StringUtil.getBytes(text);
                        }
                        if (isLatin1) {
                            builder.append(textInternalBytes,
                                    firstByteIndex,
                                    i + 1 - firstByteIndex);
                        } else {
                            builder.append(textInternalBytes,
                                    firstByteIndex,
                                    (i + 1) * 2 - firstByteIndex);
                        }
                        if (builder.entryCount() >= maxNumberOfUnwantedWordsToReturn) {
                            return builder.build(coder, UNWANTED_WORD_DELIMITER);
                        }
                    }
                }
            } else if (newChars instanceof Character c) {
                nextState = transition(currentState, c);
                while (nextState == STATUS_NOT_FOUND) {
                    currentState = fail[currentState];
                    if (currentState == ROOT_STATUS) {
                        firstByteIndex = isLatin1
                                ? i
                                : i * 2;
                    }
                    nextState = transition(currentState, c);
                }
                currentState = nextState;
                if (output[currentState] != null) {
                    if (builder == null) {
                        builder = new FastStringBuilder();
                        textInternalBytes = StringUtil.getBytes(text);
                    }
                    if (isLatin1) {
                        builder.append(textInternalBytes, firstByteIndex, i + 1 - firstByteIndex);
                    } else {
                        builder.append(textInternalBytes,
                                firstByteIndex,
                                (i + 1) * 2 - firstByteIndex);
                    }
                    if (builder.entryCount() >= maxNumberOfUnwantedWordsToReturn) {
                        return builder.build(coder, UNWANTED_WORD_DELIMITER);
                    }
                }
            }
        }
        if (builder == null) {
            return null;
        }
        return builder.build(coder, UNWANTED_WORD_DELIMITER);
    }
@param maxNumberOfUnwantedWordsToReturn should be greater than 0
turms-plugins/turms-plugin-antispam/src/main/java/im/turms/plugin/antispam/core/SpamDetector.java