Есть строка:
String text = " I hate spam."
Также есть массив строк:
String[] keywords = new String[] { "spam", "spamer" };
Необходимо проверить, имеется ли в text
такой же "spam"
как и в keywords
.
В каком направлении двигаться для решения задачи?
Предположим, что нужно проверять, содержится ли хотя бы одно ключевое слово (стоп-слово) в заданной строке.
Полный перебор ключевых слов с проверкой с помощью метода contains
private static boolean bruteForce(String text, String[] keywords)
{
for (String keyword : keywords)
{
if (text.contains(keyword))
{
return true;
}
}
return false;
}
прост в реализации и быстро работает при небольшой длине строки и небольшом количестве ключевых строк.
Однако при большом объёме данных этот алгоритм начинает работать достаточно долго.
При длине строки в миллион символов и 10 тысячах ключевых слов (длина каждого - 20 символов) у меня алгоритм работает 3100-3200мс при условии, что в строке есть только последнее ключевое слово в конце строки.
В этом случае можно, например, построить ДКА на базе ключевых слов, после чего пользоваться им для поиска совпадений в строке.
Представленный ниже алгоритм отличается от алгоритма Ахо - Корасик в плане обработки несовпадения подстроки, однако работает всё равно достаточно быстро (на тех же данных - 60-70мс).
При проверке множества строк на одни и те же ключевые слова имеет смысл построить ДКА один раз и в дальнейшем использовать его для всех строк. В таком случае время обработки для исходной строки снизится до 40-50мс.
Класс состояния ДКА с учетом оптимизации:
private static class State
{
private Map<Character, State> transitions;
public boolean isFinal = false;
private char firstChar;
private State firstState = null;
public State get(char c)
{
if (firstState != null && firstChar == c)
{
return firstState;
}
if (transitions != null)
{
return transitions.get(c);
}
return null;
}
public State getOrCreate(char c)
{
if (firstState != null && firstChar == c)
{
return firstState;
}
if (firstState == null)
{
firstState = new State();
firstChar = c;
return firstState;
}
if (transitions == null)
{
transitions = new HashMap<>();
}
State state = transitions.get(c);
if (state == null)
{
state = new State();
transitions.put(c, state);
}
return state;
}
}
Формирование ДКА и поиск по строке:
private static boolean dfa(String text, String[] keywords)
{
State root = new State();
for (String keyword : keywords)
{
State state = root;
for (char c : keyword.toCharArray())
{
state = state.getOrCreate(c);
}
state.isFinal = true;
}
State state = root;
int foundSymbols = 0;
for (int i = 0; i < text.length(); i++)
{
state = state.get(text.charAt(i));
if (state == null)
{
i -= foundSymbols;
state = root;
foundSymbols = 0;
}
else if (state.isFinal)
{
return true;
}
else
{
foundSymbols++;
}
}
return false;
}
Нашел способ! :)
text.contains(String.valueOf(keywords[0]));
ну а keywords, соответственно в цикл для перебора по индексу
Можно попробовать так:
String text = " I hate spam.";
String[] keywords = new String[] {"spam", "spamer"};
boolean isContains = false;
for (String s : keywords) {
if (text.contains(s)) {
isContains = true;
break;
}
}
if (isContains) {
// слово содержится...
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Добрый деньНикак не могу понять как переименовывать файл в Java, т
Пишу простую программу для шифрования данных в AndroidСтолкнулся с такой проблемой, что нет доступа на запись к exSDcard устройств
Заинтерисовал меня такой вопрос, возможно ли сделать так, что бы jar нельзя было бы открыть с помощью winrarПытался завернуть в exe с помощью launch4j,...