I need to find the longest sequence in a string with the caveat that the sequence must be repeated three or more times. So, for example, if my string is:
fdwaw4helloworldvcdv1c3xcv3xcz1sda21f2sd1ahelloworldgafgfa4564534321fadghelloworld
then I would like the value “helloworld” to be returned.
I know of a few ways of accomplishing this but the problem I’m facing is that the actual string is absurdly large so I’m really looking for a method that can do it in a timely fashion.
djechlin
58.8k34 gold badges161 silver badges288 bronze badges
asked Jun 18, 2012 at 20:09
1
This problem is a variant of the longest repeated substring problem and there is an O(n)-time algorithm for solving it that uses suffix trees. The idea (as suggested by Wikipedia) is to construct a suffix tree (time O(n)), annotate all the nodes in the tree with the number of descendants (time O(n) using a DFS), and then to find the deepest node in the tree with at least three descendants (time O(n) using a DFS). This overall algorithm takes time O(n).
That said, suffix trees are notoriously hard to construct, so you would probably want to find a Python library that implements suffix trees for you before attempting this implementation. A quick Google search turns up this library, though I’m not sure whether this is a good implementation.
Another option would be to use suffix arrays in conjunction with LCP arrays. You can iterate over pairs of adjacent elements in the LCP array, taking the minimum of each pair, and store the largest number you find this way. That will correspond to the length of the longest string that repeats at least three times, and from there you can then read off the string itself.
There are several simple algorithms for building suffix arrays (the Manber-Myers algorithm runs in time O(n log n) and isn’t too hard to code up), and Kasai’s algorithm builds LCP arrays in time O(n) and is fairly straightforward to code up.
Hope this helps!
answered Jun 18, 2012 at 20:17
templatetypedeftemplatetypedef
360k101 gold badges890 silver badges1059 bronze badges
5
Use defaultdict to tally each substring beginning with each position in the input string. The OP wasn’t clear whether overlapping matches should or shouldn’t be included, this brute force method includes them.
from collections import defaultdict
def getsubs(loc, s):
substr = s[loc:]
i = -1
while(substr):
yield substr
substr = s[loc:i]
i -= 1
def longestRepetitiveSubstring(r, minocc=3):
occ = defaultdict(int)
# tally all occurrences of all substrings
for i in range(len(r)):
for sub in getsubs(i,r):
occ[sub] += 1
# filter out all substrings with fewer than minocc occurrences
occ_minocc = [k for k,v in occ.items() if v >= minocc]
if occ_minocc:
maxkey = max(occ_minocc, key=len)
return maxkey, occ[maxkey]
else:
raise ValueError("no repetitions of any substring of '%s' with %d or more occurrences" % (r,minocc))
prints:
('helloworld', 3)
answered Jun 18, 2012 at 21:36
PaulMcGPaulMcG
62k16 gold badges93 silver badges130 bronze badges
1
Let’s start from the end, count the frequency and stop as soon as the most frequent element appears 3 or more times.
from collections import Counter
a='fdwaw4helloworldvcdv1c3xcv3xcz1sda21f2sd1ahelloworldgafgfa4564534321fadghelloworld'
times=3
for n in range(1,len(a)/times+1)[::-1]:
substrings=[a[i:i+n] for i in range(len(a)-n+1)]
freqs=Counter(substrings)
if freqs.most_common(1)[0][1]>=3:
seq=freqs.most_common(1)[0][0]
break
print "sequence '%s' of length %s occurs %s or more times"%(seq,n,times)
Result:
>>> sequence 'helloworld' of length 10 occurs 3 or more times
Edit: if you have the feeling that you’re dealing with random input and the common substring should be of small length, you better start (if you need the speed) with small substrings and stop when you can’t find any that appear at least 3 time:
from collections import Counter
a='fdwaw4helloworldvcdv1c3xcv3xcz1sda21f2sd1ahelloworldgafgfa4564534321fadghelloworld'
times=3
for n in range(1,len(a)/times+1):
substrings=[a[i:i+n] for i in range(len(a)-n+1)]
freqs=Counter(substrings)
if freqs.most_common(1)[0][1]<3:
n-=1
break
else:
seq=freqs.most_common(1)[0][0]
print "sequence '%s' of length %s occurs %s or more times"%(seq,n,times)
The same result as above.
answered Jun 18, 2012 at 21:31
Max LiMax Li
5,0013 gold badges22 silver badges35 bronze badges
3
The first idea that came to mind is searching with progressively larger regular expressions:
import re
text = 'fdwaw4helloworldvcdv1c3xcv3xcz1sda21f2sd1ahelloworldgafgfa4564534321fadghelloworld'
largest = ''
i = 1
while 1:
m = re.search("(" + ("w" * i) + ").*\1.*\1", text)
if not m:
break
largest = m.group(1)
i += 1
print largest # helloworld
The code ran successfully. The time complexity appears to be at least O(n^2).
answered Jun 18, 2012 at 21:11
Matt CoughlinMatt Coughlin
18.6k3 gold badges46 silver badges59 bronze badges
1
If you reverse the input string, then feed it to a regex like (.+)(?:.*1){2}
It should give you the longest string repeated 3 times. (Reverse capture group 1 for the answer)
Edit:
I have to say cancel this way. It’s dependent on the first match. Unless its tested against a curr length vs max length so far, in an itterative loop, regex won’t work for this.
answered Jun 18, 2012 at 22:00
In Python you can use the string count method.
We also use an additional generator which will generate all the unique substrings of a given length for our example string.
The code is straightforward:
test_string2 = 'fdwaw4helloworldvcdv1c3xcv3xcz1sda21f2sd1ahelloworldgafgfa4564534321fadghelloworld'
def generate_substrings_of_length(this_string, length):
''' Generates unique substrings of a given length for a given string'''
for i in range(len(this_string)-2*length+1):
yield this_string[i:i+length]
def longest_substring(this_string):
'''Returns the string with at least two repetitions which has maximum length'''
max_substring = ''
for subs_length in range(2, len(this_string) // 2 + 1):
for substring in generate_substrings_of_length(this_string, subs_length):
count_occurences = this_string.count(substring)
if count_occurences > 1 :
if len(substring) > len(max_substring) :
max_substring = substring
return max_substring
I must note here (and this is important) that the generate_substrings_of_length generator does not generate all the substrings of a certain length. It will generate only the required substring to be able to make comparisons. Otherwise we will have some artificial duplicates. For example in the case :
test_string = "banana"
GS = generate_substrings_of_length(test_string , 2)
for i in GS: print(i)
will result :
ba
an
na
and this is enough for what we need.
answered Feb 18 at 10:52
youth4everyouth4ever
1984 silver badges13 bronze badges
from collections import Counter
def Longest(string):
b = []
le = []
for i in set(string):
for j in range(Counter(string)[i]+1):
b.append(i* (j+1))
for i in b:
if i in string:
le.append(i)
return ([s for s in le if len(s)==len(max( le , key = len))])
xskxzr
12.3k12 gold badges37 silver badges76 bronze badges
answered Mar 12, 2019 at 16:07
Необходимо найти максимальную по длине последовательность цифр в строке.
lists = [] # Создание пустого массива
inputString = input("Введите строку: ") #Ввод исходной строки
xArr = list(inputString) # Разбитие строки на массив из элементов строки
MaxInt = 0 # Максимальная длина чисел
index = 0 # индекс массива xArr
while index <= len(xArr): # Пока индекс меньше равен длине Массива
if type(xArr[index]) == int: # если индекс равен числовому типу
MaxInt = MaxInt + 1 # инкремент Длины чисел
index += 1 # инкремент индекса
if type(xArr[index + 1]) == str or index == len(xArr): # если след символ
# строки символ или конец строки
lists.append(MaxInt) # добавление в конец массива с макс значениями
#текущую макс длину цифр
MaxInt = 0 # обнуляю макс значение
break # останавливаю цикл
print(max(lists)) # Макс значение из массива с макс значениями
Blacit
1,3751 золотой знак16 серебряных знаков37 бронзовых знаков
задан 6 ноя 2019 в 12:43
5
Это можно очень просто решить регулярными выражениями.
Регулярное выражение d+
ищет последовательности цифр, а re.findall
вернет строки с результатом.
Останется список строк превратить в список длин строк и получить максимальное значение.
Пример:
import re
text = input("Введите строку: ")
items = re.findall('d+', text)
max_len = max(len(x) for x in items)
print(max_len)
Консоль:
Введите строку: 12 abcsd232 df12124 5555555
7
UPD.
Через цикл:
text = '12 abcsd232 df12124 5555555'
max_len = 0
cur_len = 0
for c in text:
if c in '0123456789':
cur_len += 1
else:
if cur_len > max_len:
max_len = cur_len
cur_len = 0
if cur_len > max_len:
max_len = cur_len
print(max_len) # 7
Или:
text = '12 abcsd232 df12124 5555555'
max_len = 0
cur_len = 0
for i in range(len(text)):
c = text[i]
if c in '0123456789':
cur_len += 1
elif cur_len > max_len:
max_len = cur_len
cur_len = 0
# Конец строки
if i == len(text) - 1 and cur_len > max_len:
max_len = cur_len
print(max_len) # 7
ответ дан 6 ноя 2019 в 12:57
gil9redgil9red
76.3k6 золотых знаков51 серебряный знак117 бронзовых знаков
4
input()
всегда выдает строку, поэтому условие if type(xArr[index]) == int
не выполнится никогда. Нужно его заменить, например, на такое:
if xArr[index] in "0123456789":
Второй if
просто заменить на else
и убрать оттуда break
конечно же. То условие не делает ничего нужного.
ответ дан 6 ноя 2019 в 12:59
ЭникейщикЭникейщик
25.1k7 золотых знаков30 серебряных знаков46 бронзовых знаков
1
input возвращает str.
В цикле необходимо делать проверку с помощью метода str.isdigit().
Так же можно через ord(), зная какие коды возвращают цифры.
ответ дан 6 ноя 2019 в 14:17
sdmntsdmnt
54 бронзовых знака
a= '12 abcsd232 df12124 5555555'
maxdig = max(len(b) for b in ''.join([a[i] if a[i].isdigit() else ' ' for i in range(len(a))]).split())
print(maxdig)
Идея простая.
-
из строки делаем новую, заменяя не-цифры на пробелы
''.join([a[i] if a[i].isdigit() else ' ' for i in range(len(a))
-
Делаем генератор выражения, разделяя по пробелу и
а
в качестве выражения длины. Ищем максимум.
ответ дан 16 ноя 2022 в 11:10
Ученик
(85),
на голосовании
2 года назад
Голосование за лучший ответ
port port
Искусственный Интеллект
(181477)
2 года назад
На тебе for…
s=’ssbbbsssbc’
count=0
result=0
for i in s:
~~if i==’s’: count+=1
~~else:
~~~~if count>result: result=count; count=0
if count>result: result=count;
print (result)
Сергей ВилковУченик (85)
2 года назад
Результат получается = 5, а это не правильно. Вы считаете общее количество “s”, а не самую длинную её последовательность.
Сергей ВилковУченик (85)
2 года назад
И всё-равно вы считаете общую сумму “s”, а в условие задачи нужно: подсчитывать самую длинную последовательность подряд идущих букв “s” и выводит ответ на экран?
Тимур Пономарёв
Мастер
(1432)
2 года назад
Что тут интересного? Если тебе нужно написать программу то просто иди в цикле for до конца строки и символы сравнивает
stroka = input()
counter = 1
max = 0
for i in range(1, len(stroka)):
____if stroka[i] == stroka[i-1] == ‘s’:
________counter = counter + 1
________if counter > max:
____________max = counter
____else:
________counter = 1
print(max)
Veter .
Мастер
(1105)
2 года назад
Сергей ВилковУченик (85)
2 года назад
Вот в этом то и дело (и вся сложность простой задачи), что нужно решить без этого!?
Сергей ВилковУченик (85)
2 года назад
Вот так можно переложить ваш код на простой “язык”!
print(‘Введите строку: ‘, end = ”)
text = input()
text += ”
count_s = 0
letter = 0
for symbol in text:
if symbol == ‘s’:
letter += 1
else:
if letter > count_s:
count_s = letter
letter = 0
print(‘Самая длинная последовательность: ‘, count_s)
SkkkN
Профи
(776)
1 год назад
string = input(‘Введите строку: ‘)
count = 0
result = 0
for symbol in string:
~~if symbol == ‘s’:
~~~~count += 1
~~elif count < result and symbol != ‘s’:
~~~~count = 0
~~else:
~~~~if count > result:
~~~~~~result = count
~~~~~~count = 0
if count > result:
~~result = count
print(‘Самая длинная последовательность: ‘, result)
Продолжаем разбирать задачи с сайта LeetCode. На этот раз — посложнее:
Есть строка s — нужно найти длину самой длинной подстроки, в которой каждый символ используется только один раз.
Например:
если s = “abcabcbb”, то ответ будет 3, потому что строка без повторений — это “abc”;
если s = “bbbbb”, то ответ будет 1, потому что самая длинная подстрока тут будет из одного символа;
если s = “pwwkew”, то ответ будет 3, потому что тут две самые одинаково длинные подстроки — “wke” и “kew”, в которых по 3 символа.
Такие алгоритмы иногда используются для выявления закономерностей и поиска общих элементов, поэтому их тоже могут спросить на собеседованиях.
Решение: использовать встроенные функции для работы со строками
Самое простое решение — собирать отдельную подстроку из символов и смотреть каждый раз, есть очередной символ в этой подстроке или нет. Если нет — добавляем его в конец и смотрим дальше. А если очередной символ там уже есть, то в подстроке оставляем только то, что идёт после этого символа, и добавляем туда текущий.
Например, если у нас в подстроке хранится “abcdf” и мы снова встречаем b, то делаем так:
- Получаем номер символа b в подстроке → он равен 1 (если интересно, почему не 2, — почитайте, почему счёт в программировании начинается с нуля, а не с единицы).
- Формируем новую строку, начиная с 1 символа и до конца → “cdf”.
- Добавляем к ней в конец наш текущий символ b → “cdfb”.
Так шаг за шагом мы проверим все вложенные строки и найдём самую длинную без повторов. Звучит сложно, но в коде всё выглядит гораздо проще. Почитайте комментарии, чтобы разобраться в каждом шаге:
# исходная строка
s = 'abcabcdcc'
# здесь будет наш ответ
res = 0
# на старте у нас пустая подстрока
sub = ''
# перебираем все символы в исходной строке
for char in s:
# если символа нет в подстроке
if char not in sub:
# добавляем его туда
sub += char
# смотрим, максимальный ли это результат, и если да — запоминаем его
res = max(res, len(sub))
# если символ в подстроке есть
else:
# получаем индекс текущего символа в подстроке
cut = sub.index(char)
# сокращаем нашу подстроку: оставляем только то, что идёт после символа-дубликата, и добавляем к строке текущий символ
sub = sub[cut+1:] + char
# выводим результат на экран
print(res)
Решение: проверить всю вложенную строку
Зайдём с другой стороны — напишем функцию, которая будет проверять, есть в указанной подстроке повторяющиеся символы или нет. Логика будет такая:
- Передаём в функцию начальный и конечный индекс, который определяет границы подстроки.
- Заводим массив, в который будем складывать проверенные символы и проверять на дубли.
- По очереди проверяем все символы в указанном диапазоне и смотрим, есть ли очередной символ в нашем массиве.
- Если есть — выводим False, что означает, что в подстроке есть повторяющиеся символы.
- Если символа нет — добавляем его в наш массив.
- Если мы проверили все символы и ни одного не было в том массиве — возвращаем True, то есть повторов нет.
Теперь запишем это на Python:
# исходная строка
s = 'abcabcdcc'
# функция, которая проверит, есть ли в подстроке повторяющиеся символы
# на вход отправляем начальную и конечную позицию в строке для проверки
def check(start, end):
# создаём пустое множество
chars = set()
# делаем цикл от начального до конечного символа
for i in range(start, end + 1):
# получаем очередной символ из строки
c = s[i]
# если символа уже есть в множестве
if c in chars:
# возвращаем False — в строке есть повторяющиеся символы
return False
# добавляем символ в множество
chars.add(c)
# если дошли досюда — возвращаем True
return True
Теперь перейдём к основной части. Раз мы научились проверять, есть повторы в подстроке или нет, то нам остаётся только найти и проверить все вложенные строки. Сделаем это обычным перебором с вложенным циклом: будем проверять все подстроки, сначала начиная с первого символа, потом со второго и так далее. При этом мы будем каждый раз считать и запоминать максимальную длину подстроки без повторов, которая у нас получилась:
# --- основной алгоритм ---
# получаем длину строки
n = len(s)
# здесь будет наш ответ
res = 0
# перебираем символы от первого до последнего
for i in range(n):
# перебираем символы от текущего до последнего
for j in range(i, n):
# если в получившейся подстроке нет повторяющихся символов
if check(i, j):
# смотрим, максимальный ли это результат, и если да — запоминаем его
res = max(res, j - i + 1)
# выводим результат на экран
print(res)
Объединим обе части и получим готовый код:
# исходная строка
s = 'abcabcdcc'
# функция, которая проверит, есть ли в подстроке повторяющиеся символы
# на вход отправляем начальную и конечную позицию в строке для проверки
def check(start, end):
# создаём пустое множество
chars = set()
# делаем цикл от начального до конечного символа
for i in range(start, end + 1):
# получаем очередной символ из строки
c = s[i]
# если символа уже есть в множестве
if c in chars:
# возвращаем False — в строке есть повторяющиеся символы
return False
# добавляем символ в множество
chars.add(c)
# если дошли досюда — возвращаем True
return True
# --- основной алгоритм ---
# получаем длину строки
n = len(s)
# здесь будет наш ответ
res = 0
# перебираем символы от первого до последнего
for i in range(n):
# перебираем символы от текущего до последнего
for j in range(i, n):
# если в получившейся подстроке нет повторяющихся символов
if check(i, j):
# смотрим, максимальный ли это результат, и если да — запоминаем его
res = max(res, j - i + 1)
# выводим результат на экран
print(res)
Вёрстка:
Кирилл Климентьев
29.12.2019Python, Программы Python
Если задана строка (может содержать как буквы, так и цифры), напишите программу на Python, чтобы найти самую длинную последовательность букв и цифр.
Примеры:
Input : geeks123available Output : ('available', 123) Input : 98apple658pine Output : ('apple', 658)
Подход № 1: грубая сила
Это наивный или грубый метод, позволяющий найти самую длинную последовательность букв и цифр. Мы берем две строковые переменные типа longest_letter и longest_digit . Запускаем цикл и проверяем последовательные подстроки букв и цифр. На каждой итерации мы проверяем, больше ли текущая буквенная подстрока, чем самая длинная буквенная или цифровая подстрока соответственно. Если да, мы присваиваем текущую подстроку буквы и цифры самой длинной букве и подстроке цифры соответственно. В противном случае ничего не делать.
import
re
def
longestSubstring(s):
longest_letterSeq
=
''
longest_digitSeq
=
''
i
=
0
while
(i<
len
(s)):
curr_letterSeq
=
''
curr_digitSeq
=
''
while
(i<
len
(s)
and
s[i].isalpha()):
curr_letterSeq
+
=
s[i]
i
+
=
1
while
(i<
len
(s)
and
s[i].isdigit()):
curr_digitSeq
+
=
s[i]
i
+
=
1
if
(i<
len
(s)
and
not
(s[i].isdigit())
and
not
(s[i].isalpha())) :
i
+
=
1
if
(
len
(curr_letterSeq) >
len
(longest_letterSeq) ):
longest_letterSeq
=
curr_letterSeq
if
(
len
(curr_digitSeq) >
len
(longest_digitSeq) ):
longest_digitSeq
=
curr_digitSeq
return
longest_letterSeq, longest_digitSeq
str
=
'3Geeksfor123geeks3'
print
(longestSubstring(
str
))
Выход:
('Geeksfor', '123')
Подход № 2: Использование регулярных выражений Python
Python Regex является еще одним методом решения данной проблемы. Найдите последовательность подстрок из цифр и букв, используя регулярное выражение Python, а затем найдите самую длинную длину подстроки соответственно.
import
re
def
longestSubstring(
str
):
letter
=
max
(re.findall(r
'D+'
,
str
), key
=
len
)
digit
=
max
(re.findall(r
'd+'
,
str
), key
=
len
)
return
letter, digit
str
=
'geeks123geeksforgeeks1'
print
(longestSubstring(
str
))
Выход:
('geeksforgeeks', '123')
Рекомендуемые посты:
- SequenceMatcher в Python для самой длинной общей подстроки
- Python | Найти элементы списка, начинающиеся с определенной буквы
- Карта Питона | Длина самого длинного последовательного 1 в двоичном представлении данного целого числа
- Регулярное выражение Python для поиска последовательностей из одной заглавной буквы, за которой следуют строчные буквы
- Python | Найти последнее вхождение подстроки
- Python | Способы поиска n-го вхождения подстроки в строке
- Python | Найти k самых длинных слов в данном списке
- Python | Способы проверить, содержит ли данная строка только букву
- Python | Все вхождения подстроки в строку
- Python | Получить строку после появления данной подстроки
- Python | Частота подстроки в данной строке
- Python | Добавить подстроку по определенному индексу
- Python | Удалить указанную подстроку из конца строки
- Python | Соответствие ключа подстроки в словаре
- Python | Проверьте, присутствует ли подстрока в строке
Python | Найти самую длинную последовательность букв и цифр
0.00 (0%) 0 votes