Before speaking about the actual algorithm, let me hint you at the official Style Guide for Python Code (often just called PEP 8), a set of guidelines to write idiomatic-looking Python code. A core takeaway of the read should be, that in Python lower_case_with_underscores is the preferred way to name variables and functions. Fortunately you don't have to ...
First of all, let's listen to the warning we get when we run this and get rid off it:
UserWarning: Using slow pure-python SequenceMatcher. Install
python-Levenshtein to remove this warning warnings.warn('Using slow
pure-python SequenceMatcher. Install python-Levenshtein to remove this
You can fix that by installing the ...
The more "Pythonic" way (aka using Pythonic syntactic sugar to make the code more concise) of writing this:
is_repeat = True
for n in neighbours:
is_repeat = False
is_repeat = all([coverage.get(n, 0) >= 2 for n in neighbors])
but I'm not sure this will necessarily be any more efficient.
Firstly, great job on creating a solution that works. That is often the first step in creating an optimal solution.
But as you may have noticed, making combinations and permutations based on the number of elements in small_strings will start to scale incredibly as you process longer and longer small_strings arrays.
Mathematically, your solution is ...
Think about the problem as a repeated Cartesian product. It allows us
to use the very useful product function from the itertools module:
>>> list(product('ab', 'AB', 'xy'))
[('a', 'A', 'x'), ('a', 'A', 'y'), ('a', 'B', 'x'),
('a', 'B', 'y'), ('b', 'A', 'x'), ('b', 'A', 'y'),
('b', 'B', 'x'), ('b', 'B', 'y')]
So your problem can be solved by ...