Помогите поправить цикл.
Нужно найти подстроку максимальной длины, состоящую из одного и того же символа идущего подряд.
Например, есть строка “acccabcfbbffffffcccc”, нужно вывести число 6, потому что ffffff – это максимальная подстрока.
Сделать надо одним циклом.
Начало такое:
public static int getMaxCharInSubstring(String inputString) {
if (inputString.isEmpty()) {
return -1;
}
int countCharsInSubString = 0;
int countCharsInSubStringTemp = 0;
inputString = inputString.toUpperCase();
for (int i = 0; i < inputString.length() - 1; ++i) {
if (inputString.charAt(i) == inputString.charAt(i + 1)) {
countCharsInSubStringTemp +=1;
++i;
if (countCharsInSubStringTemp > countCharsInSubString) {
countCharsInSubString = countCharsInSubStringTemp;
}
}
}
return countCharsInSubString;
}
gil9red
76.3k6 золотых знаков51 серебряный знак117 бронзовых знаков
задан 9 апр 2018 в 9:43
2
Если использовать регулярное выражение, то получится очень красивый и простой алгоритм:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String text = "acccabcfbbffffffcccc";
int maxLen = 0;
Matcher m = Pattern.compile("(.)\1+").matcher(text);
while (m.find()) {
String sub = m.group();
System.out.println(sub);
if (sub.length() > maxLen) {
maxLen = sub.length();
}
}
System.out.println("nmaxLen: " + maxLen);
}
}
Консоль:
ccc
bb
ffffff
cccc
maxLen: 6
Регулярка (.)\1+
говорит о том, что ищем любой символ, после которого сразу идет 1 или больше таких же символов
ответ дан 9 апр 2018 в 10:12
gil9redgil9red
76.3k6 золотых знаков51 серебряный знак117 бронзовых знаков
Проблема у вас была в условии. Проверяем, если символ равен следующему символу буфер countCharsInSubStringTemp
увеличиваем на 1, но как только мы определили, что следующий символ не равен предыдущему, то делается проверка countCharsInSubString< countCharsInSubStringTemp
, если так, то устанавливаем максимальное количество символов равное countCharsInSubStringTemp
и обнуляем:
public static int getMaxCharInSubstring(String inputString) {
if (inputString.isEmpty()) {
return -1;
}
int countCharsInSubString = 0;
int countCharsInSubStringTemp = 0;
inputString = inputString.toUpperCase();
int length = inputString.length();
for (int i = 0; i < length; i++) {
if (inputString.charAt(i) == inputString.charAt(i + 1)) {
countCharsInSubStringTemp +=1;
}else
if (countCharsInSubStringTemp > countCharsInSubString) {
countCharsInSubString = countCharsInSubStringTemp;
countCharsInSubStringTemp=0;
}
}
}
return countCharsInSubString;
}
ответ дан 9 апр 2018 в 9:58
СанаевСанаев
1,8751 золотой знак9 серебряных знаков29 бронзовых знаков
5
Получилось так:
int countCharsInSubString = 0;
int countCharsInSubStringTemp = 0;
for (int i = 0; i < inputString.length() - 1; ++i) {
if (inputString.charAt(i) == inputString.charAt(i + 1)) {
countCharsInSubStringTemp += 1;
} else if (countCharsInSubStringTemp > countCharsInSubString) {
countCharsInSubString = countCharsInSubStringTemp;
countCharsInSubStringTemp = 0;
}
}
if (countCharsInSubStringTemp > countCharsInSubString) {
return (countCharsInSubStringTemp + 1);
} else return (countCharsInSubString + 1);
}
ответ дан 9 апр 2018 в 12:11
Noob SabotNoob Sabot
191 серебряный знак3 бронзовых знака
Using JavaScript, I need to check if a given string contains a sequence of repeated letters, like this:
“aaaaa”
How can I do that?
asked May 30, 2011 at 13:08
3
You can use this function:
function hasRepeatedLetters(str) {
var patt = /^([a-z])1+$/;
var result = patt.test(str);
return result;
}
answered May 30, 2011 at 13:16
melhosseinymelhosseiny
9,9426 gold badges30 silver badges48 bronze badges
4
Use regular expressions:
var hasDuplicates = (/([a-z])1/i).test(str)
Or if you don’t want to catch aA
and the likes
var hasDuplicates = (/([a-zA-Z])1/).test(str)
Or, if you’ve decided you want to clarify your question:
var hasDuplicates = (/^([a-zA-Z])1+$/).test(str)
answered May 30, 2011 at 13:17
EricEric
94.7k52 gold badges239 silver badges370 bronze badges
This will check if the string has repeats more than twice:
function checkStr(str) {
str = str.replace(/s+/g,"_");
return /(S)(1{2,})/g.test(str);
}
answered May 26, 2012 at 3:12
BillyBilly
7781 gold badge7 silver badges17 bronze badges
1
Try using this
checkRepeat = function (str) {
var repeats = /(.)1/;
return repeats.test(str)
}
Sample usage
if(checkRepeat ("aaaaaaaa"))
alert('Has Repeat!')
answered May 30, 2011 at 13:35
DeveloperXDeveloperX
4,62316 silver badges22 bronze badges
function check(str) {
var tmp = {};
for(var i = str.length-1; i >= 0; i--) {
var c = str.charAt(i);
if(c in tmp) {
tmp[c] += 1;
}
else {
tmp[c] = 1;
}
}
var result = {};
for(c in tmp) {
if(tmp.hasOwnProperty(c)) {
if(tmp[c] > 1){
result[c] = tmp[c];
}
}
}
return result;
}
then you can check the result to get the repeated chars and their frequency. if result is empty, there is no repeating there.
Eric
94.7k52 gold badges239 silver badges370 bronze badges
answered May 30, 2011 at 13:12
wong2wong2
33.9k48 gold badges133 silver badges178 bronze badges
1
I solved that using a for loop, not with regex
//This check if a string has 3 repeated letters, if yes return true, instead return false
//If you want more than 3 to check just add another validation in the if check
function stringCheck (string) {
for (var i = 0; i < string.length; i++)
if (string[i]===string[i+1] && string[i+1]===string[i+2])
return true
return false
}
var str1 = "hello word" //expected false
var str2 = "helllo word" //expredted true
var str3 = "123 blAAbA" //exprected false
var str4 = "hahaha haaa" //exprected true
console.log(str1, "<==", stringCheck(str1))
console.log(str2, "<==", stringCheck(str2))
console.log(str3, "<==", stringCheck(str3))
console.log(str4, "<==", stringCheck(str4))
answered Dec 19, 2017 at 20:33
var char = "abcbdf..,,ddd,,,d,,,";
var tempArry={};
for (var i=0; i < char.length; i++) {
if (tempArry[char[i]]) {
tempArry[char[i]].push(char[i]);
} else {
tempArry[char[i]] = [];
tempArry[char[i]].push(char[i]);
}
}
console.log(tempArry);
This will even return the number of repeated characters also.
nhahtdh
55.8k15 gold badges126 silver badges162 bronze badges
answered Sep 2, 2013 at 2:58
user2364729user2364729
2093 silver badges4 bronze badges
Содержание
- Суть алгоритма
- Реализация алгоритма поиска наибольшей повторяющейся подстроки в C#
- Результат работы программы
- Итого
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Последовательность — это некий упорядоченный набор элементов. Строка — это частный случай последовательности. В свою очередь, под термином «наибольшая общая подстрока» мы будем понимать такую подстроку максимальной длины, которая входит в две или больше строки. Представленный ниже алгоритм также подойдет и для поиска наибольшей повторяющейся последовательности не только букв, но и, в принципе, любых символов, например, цифр.
Суть алгоритма
Для того, чтобы найти наибольшую повторяющуюся последовательность символов, например, для строк A и B, необходимо заполнить таблицу (двумерный массив) размером n на m, где n и m — длины первой (A) и второй (B) строк, по следующим правилам:
- Если
A[i] == B[j]
то:- для
i == 0 || j == 0
, Array[i, j] = 1 - для
i > 0 && j > 0
, Array[i, j] = Array[i — 1, j — 1] + 1
- для
Например, рассмотрим две строки: «ПОИСК» и «ПИСК» (наибольшая повторяющаяся подстрока в этом случае — «ИСК»):
Реализация алгоритма поиска наибольшей повторяющейся подстроки в C#
Код консольного приложения для поиска набольшей повторяющейся подстроки представлен ниже:
using System; namespace ConsoleApp1 { internal class Program { static string LCS(string a, string b) { var n = a.Length; //длина первой строки var m = b.Length; //длина второй строки var array = new int[n, m]; //создаем двумерный массив m x n var maxValue = 0; var maxI = 0; for (int i = 0; i < n; i++) //цикл по символам строки A { for (int j = 0; j < m; j++) //цикл по символам строки B { if (a[i] == b[j]) //проверяем совпадают ли символы в позициях i и j { array[i, j] = (i == 0 || j == 0) ? 1 : array[i - 1, j - 1] + 1; if (array[i, j] > maxValue) { maxValue = array[i, j];//максимальное количество повторяющихся символов maxI = i; //запоминаем позицию в строке A с которой необходимо начать копирование подстроки } } } } //возвращаем наибольшую повторяющуюся подстроку return a.Substring(maxI + 1 - maxValue, maxValue); } static void Main(string[] args) { Console.Write("Первое слово: "); var a = Console.ReadLine(); Console.Write("Второе слово: "); var b = Console.ReadLine(); Console.WriteLine($"Наибольшая общая подстрока: {LCS(a, b)}"); Console.ReadLine(); } } }
Результат работы программы
Первое слово: поиск
Второе слово: писк
Наибольшая общая подстрока: иск
Внимание: в представленном выше алгоритме при поиске учитывается регистр символов в строках, то есть для подстрок «поиск» и «пИск» наибольшей повторяющейся подстрокой будет «ск», так как во втором слове буква «И» стоит в верхнем регистре.
Итого
Для реализации алгоритма поиска наибольшей повторяющейся последовательности нам понадобились знания о том, что из себя представляет массив и умение работать с циклами (в данном случае — с циклом for
).
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Ниже приведен пример Java, который ищет и удаляет повторяющиеся символы из заданной строки.
Пример
import java.util.Arrays; import org.apache.commons.lang3.ArrayUtils; public class DuplicateSample { public static void main(String args[]){ String str = "malayalam"; char[] myArray = str.toCharArray(); for(int i=0; i<myArray.length-1; i++){ for (int j=i+1; j<myArray.length; j++){ if(myArray[i] == myArray[j]){ myArray = ArrayUtils.remove(myArray, j); } } } System.out.println("String value after deleting the duplicate values :"+Arrays.toString(myArray)); } }
Итог
String value after deleting the duplicate values :[m, a, l, y]
Эти символы можно найти с помощью вложенного цикла for. Пример этого приведен ниже:
String = Apple
В приведенной выше строке p является повторяющимся символом, так как встречается более одного раза.
Пример
public class Example { public static void main(String argu[]) { String str = "beautiful beach"; char[] carray = str.toCharArray(); System.out.println("The string is:" + str); System.out.print("Duplicate Characters in above string are: "); for (int i = 0; i < str.length(); i++) { for (int j = i + 1; j < str.length(); j++) { if (carray[i] == carray[j]) { System.out.print(carray[j] + " "); break; } } } } }
Вывод
The string is:beautiful beach Duplicate Characters in above string are: b e a u
Сначала определяется строка str. Затем str.toCharArray() преобразует строку в последовательность символов. Исходная строка отображается. Фрагмент кода, демонстрирующий это, приведен ниже:
String str = "beautiful beach"; char[] carray = str.toCharArray(); System.out.println("The string is:" + str);
Дублирующиеся символы находятся в строке с использованием вложенного цикла for. Затем эти символы отображаются.
System.out.print("Duplicate Characters in above string are: "); for (int i = 0; i < str.length(); i++) { for (int j = i + 1; j < str.length(); j++) { if (carray[i] == carray[j]) { System.out.print(carray[j] + " "); break; } } }
Понадобилось мне для одной программы найти в строке все последовательности одинаковых символов, и провести с ними необходимые операции (допустим, посчитать и вывести на экран – сейчас это не важно).
Я хочу написать функцию, которой можно было бы скормить передать строку, адрес массива указателей – и получить заполненный массив указателей, каждый элемент которого указывал бы на начало каждой последовательности в строке. Раз уж так, почему бы не посчитать заодно количество последовательностей в строке? Пусть эта функция возвращает значение типа integer – количество найденных последовательностей.
Отлично, теперь пора перейти к реализации.
Считываю строку в массив
Мне понадобится символьный массив размером N, массив указателей на тип char (тоже размером N), переменная для хранения количества последовательностей, счётчик для цикла вывода последовательностей и… всё.
#include <stdio.h>
#define N 256
/* Прототип будущей функции */
int findSequences(const char *arr, char **arrPtr);
int main() {
char charray[N];
char *sequence[N];
int count = 0;
int i;
printf("Please enter string:n> ");
fgets(charray, N, stdin);
count = findSequences(charray, sequence);
// ...
return 0;
}
/* Полное описание функции */
int findSequences(const char *arr, char **arrPtr) {
// невидимый текст ;)
}
Кое-что о функциях и их прототипах
Прототип функции не является обязательным элементом программы. Он необходим, если нужно обратиться к функции до её полного объявления, и для проверки передаваемых функции параметров. Например, я мог бы написать полное объявление функции findSequences() до функции main() – в таком случае, мне не потребовался бы её прототип. Но у данного способа объявления функций есть два недостатка:
- Во-первых, если функций много, то главная функция main(), с которой начинается выполнеие любой программы на Си, оказывается где-то далеко в конце файла исходника. Читать такой код стороннему человеку, да и самому тоже, неудобно.
- Во-вторых,иногда нужно сделать так, чтобы функция f1 вызывала функцию f2, а дать полное описание функции f2 до её использования в функции f1 не представляется возможным. А если из функции f1 нужно вызвать f2, а из f2 – f1 (т.е. необходима косвенная рекурсия)? Тогда без прототипов никак не обойтись.
Но при использовании прототипов функций есть одна вещь, которую нужно всегда держать в голове – если я изменил название функции, тип/количество/название принимаемых параметров, тип возвращаемого функцией значения и т.п. – нужно будет изменить и прототип этой функции. Таким образом, мне нужно будет производить изменения в двух местах программы.
Разумеется, никто не требует давать полное описание всех функций до main(), или же после – и использовать прототипы. Можно комбинировать эти два метода, в зависимости от удобства и задачи.
Всё это, конечно, хорошо, но… что насчёт функции findSequences()?
В поисках последовательностей…
Посмотрим ещё раз на прототип функции findSequences():
int findSequences(const char *arr, char **arrPtr);
Ясно, что она возвращает значение типа integer. А в качестве параметров принимает ссылку на начало строки (т.е. на начало символьного массива charray, в котором хранится строка), и указатель на массив указателей. Причём, ключевое слово const перед типом параметра говорит, что этот параметр ни за что, ни при каких условиях не должен (и не будет) изменяться. Что мне и нужно – я хочу, чтобы функция только искала и считала последовательности в строке, а не портила её.
Пришло время заглянуть внутрь функции.
int findSequences(const char *arr, char **arrPtr) {
char *p = arr;
int count = 0;
arrPtr[0] = p;
while(*p && ('n' != *p))
if(*p != *(p+1))
arrPtr[++count] = ++p;
else
p++;
return count;
}
В начале, я создаю указатель на тип char и присваиваю ему адрес первого элемента массива arr. Соответственно, первый элемент массива указателей arrPtr должен содержать ссылку на первый элемент arr (т.к. начало массива – это начало последовательности).
В цикле я перемещаюсь по массиву arr слева направо, перемещая указатель вправо с каждой итерацией. То есть, я прибавляю к указателю единицу, и он смещается вправо по массиву… нет, не на единицу. Он смещается на одну ячейку массива, т.е. на длину типа char.
Цикл while() работает, пока символ по адресу p не равен 0 (т.е. не достигнут конец строки) и не равен ‘n’ (т.е. символу перевода строки). Звёздочка ‘*’ перед указателем p говорит о том, что я работаю не самим указателем, а с данными, на которые он указывает. В цикле я делаю проверку на определённое событие – если символ *p не равен символу *(p+1), т.е. символу в следующей ячейке массива, то я увеличиваю счётчик найденных последовательностей на 1, передвигаю указатель вправо, чтобы он указывал на следующую ячейку массива, и сохраняю его адрес в массиве указателей. Поскольку знак инкремента ‘++’ стоит до переменной, которую он увеличивает – то действие инкремента, т.е. увеличения значения переменной на единицу, происходит до того, как её значение будет использовано в выражении.
По завершению цикла, я возвращаю значение count, т.е. количество найденных последовательностей в строке.
Последнее, что осталось сделать после работы этой функции – это воспользоваться полученными данными. Например, вывести все последовательности, или найти длиннейшую из них.