Генерация подпоследовательностей
У меня есть строка типа "0189", для которой мне нужно сгенерировать все подпоследовательности, но порядок отдельных символов должен быть сохранен, т. Е. Здесь 9 не должно предшествовать 0, 1 или 8. Пример: 0, 018, 01 09, 0189, 18, 19, 019 и т. Д.
Другим примером является "10292", для которого подпоследовательности будут: 1, 10, 02, 02, 09, 29, 92 и т. Д. Как вы могли заметить, "02" два раза, поскольку "2" встречается дважды в данной строке. Но опять же, такие вещи, как: 21, 01, 91 являются недействительными, так как порядок должен поддерживаться.
Любой алгоритм или псевдо-код, который может быть реализован на C/C++, будет принят!
4 ответа
Я бы порекомендовал использовать естественное соответствие между набором степеней последовательности и набором двоичных чисел из 0
в 2^n - 1
, где n
длина последовательности.
В твоем случае, n
4, поэтому рассмотрим 0 = 0000
.. 15 = 1111
; где есть 1
в двоичное выражение включите соответствующий элемент из последовательности. Для этого вам понадобятся битовые сдвиги и двоичные операции:
for (int i = 0; i < (1 << n); ++i) {
std::string item;
for (j = 0; j < n; ++j) {
if (i & (1 << j)) {
item += sequence[j];
}
}
result.push_back(item);
}
Также подумайте, как бы вы обрабатывали последовательности дольше, чем это может быть int
(подсказка: рассмотрите переполнение и арифметический перенос).
Попробуйте рекурсивный подход:
- множество подпоследовательностей можно разбить на те, которые содержат первый символ, и те, которые его не содержат
- те, которые содержат первый символ, создаются путем добавления этого символа к подпоследовательностям, которые его не содержат (+ подпоследовательность, которая содержит только первый символ)
В Python:
In [29]: def subseq(s): return ' '.join((' '.join(''.join(x) for x in combs(s,n)) for n in range(1, len(s)+1)))
In [30]: subseq("0189")
Out[30]: '0 1 8 9 01 08 09 18 19 89 018 019 089 189 0189'
In [31]: subseq("10292")
Out[31]: '1 0 2 9 2 10 12 19 12 02 09 02 29 22 92 102 109 102 129 122 192 029 022 092 292 1029 1022 1092 1292 0292 10292'
In [32]:
__author__ = 'Robert'
from itertools import combinations
g = combinations(range(4), r=2)
print(list(g)) #[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
def solve(string_):
n = len(string_)
for repeat in range(1, len(string_) + 1):
combos = combinations(range(len(string_)), r=repeat)
for combo in combos:
sub_string = "".join(string_[i] for i in combo)
yield sub_string
print(list(solve('0189'))) #['0', '1', '8', '9', '01', '08', '09', '18', '19', '89', '018', '019', '089', '189']
#using recursion
def solve2(string_, i):
if i >= len(string_):
return [""] #no sub_strings beyond length of string_
character_i = string_[i]
all_sub_strings = solve2(string_, i + 1)
all_sub_strings += [character_i + sub_string for sub_string in all_sub_strings]
return all_sub_strings
print(solve2('0189', 0)) #['', '9', '8', '89', '1', '19', '18', '189', '0', '09', '08', '089', '01', '019', '018', '0189']