#java #строки #подстрока
Есть задача, где входной текст разбивается на предложения, предложения на слова и др. В конце нужно собрать тот же текст воедино, но выполнив некоторые задачи. Итак, есть String sentence;. Надо удалить подстроку из слова, начинающуюся и заканчивающуюся заданными символами, например, "а" и "б". Удалить только в слове с максимальной длиной подстроки. Сам я разбил предложение на слова в цикле, искал слова, которые содержат "а" и "б" и выбирал из них самое длинное, где и удалял подстроку. Однако, слово может быть длиннее, а подстрока короче. Как это сделать лучше? Пример: есть предложение а+б_а++б_+а+++б+_++а++++б++, где + любой символ, а _ это пробел. В нашем случае должна удалиться подстрока от а до б в последнем слове (т.к. она самая длинная) и останется такое предложение: а+б_а++б_+а+++б+_++аб++.
Ответы
Ответ 1
Для простоты задачи предположним, что слова разделены только пробельными символами (имеются ввиду любые пробелы в Unicode). import java.util.regex.Pattern; import java.util.regex.Matcher; public class HelloWorld { public static void main(String[] args) { String text = "а+б а++б +а+++б+ ++а++++б++"; // паттерн означает строку, которая содержит один или более непробельных символов "\\S+" // перед которыми подстрока "а" (франгмент (?<=а) — это так называемый positive lookbehind), // после которых подстрока "б" (франгмент (?=б) — это так называемый positive lookahead). String regexPattern = "(?<=а)\\S+(?=б)"; // получаем объект для итерации по всем совпадениям Matcher matcher = Pattern.compile(regexPattern).matcher(text); // для хранения максимульной длины совпадения int maxLength = 0; // для хранения индексов самого длинного совпадения int startIndex = -1; int endIndex = -1; // итерируемся по всем совпадениям while (matcher.find()) { int length = matcher.end() - matcher.start(); // если совпадение самое длинное, то сохраняем его индексы if (length > maxLength) { startIndex = matcher.start(); endIndex = matcher.end(); } } // если совпадение найдено (оно будет самым длинным), то вырезаем его if (startIndex > 0) text = text.substring(0, startIndex) + text.substring(endIndex); System.out.println(text); } }Ответ 2
Если я верно понял задачу, то надо найти максимальную подстроку в слове (слова разделены пробелами), которая начинается на 'а', заканчивается на 'б', причем внутри этой подстроки нет ни а, ни б и удалить все символы между началои подстроки и концом. Если так, то это можно за линейное время сварганить string RemoveSubString(string str, char start, char end) { int s = -1; int e = -1; int pointer = 0; while(pointer < str.Length) { while(pointer < str.Length && str[pointer]!=start && str[pointer]!=' ') pointer++; if (pointer < str.Length && str[pointer]==start) { int s1 = pointer; pointer++; while(pointer < str.Length && str[pointer]!=end && str[pointer]!=' ') pointer++; if (pointer < str.Length && str[pointer] == end) { int e1 = pointer; if(s == -1 || (e-s) < (e1-s1)) { s=s1; e=e1; } } else pointer++; } else pointer++; } if ((e-s) < 2) return str; return str.Substring(0, s+1) + str.Substring(e, str.Length-e); } Проверка Console.WriteLine(RemoveSubString("а+б а++б +а+++б+ ++а++++б++", 'а', 'б')); Console.WriteLine(RemoveSubString("а+б_а++б_+а+++б+_++а++++б++", 'а', 'б')); Console.WriteLine(RemoveSubString("1-----2-------2--------2", '1', '2')); Console.WriteLine(RemoveSubString("12", '1', '2')); Console.WriteLine(RemoveSubString("21", '1', '2')); Console.WriteLine(RemoveSubString("2-1-2", '1', '2')); Console.WriteLine(RemoveSubString("1-2", '1', '2')); Console.WriteLine(RemoveSubString("1222222", '1', '2')); Console.WriteLine(RemoveSubString("2111111", '1', '2')); Console.WriteLine(RemoveSubString("1-111111", '1', '1')); Console.WriteLine(RemoveSubString("1-11111--1", '1', '1')); Вывод а+б а++б +а+++б+ ++аб++ а+б_а++б_+а+++б+_++аб++ 12-------2--------2 12 21 2-12 12 1222222 2111111 1111111 1-111111
Комментариев нет:
Отправить комментарий