Наивный пример s='a'*n
и p='a'*m+'b'
не работает из-за строки
if s[i+m-1] == p[m-1]:
Это проверяет последний (не первый) символ p
('b'
) ссоответствующая текущая позиция в s
.Поскольку это не удается, то результатом является всего лишь одна итерация по s
, поэтому она так быстра.
Если вы перевернете p
(s='a'*n
и p='b'+'a'*m
), тогдапроисходит то же самое - на этот раз вышеупомянутая строка проходит (последний символ p
теперь 'a'
), но затем p
перебирается вперед, поэтому затем 'b'
быстро обнаруживается, поэтому снова этот примерлинейный и быстрый.
Простое изменение наивного примера, которое показало бы поведение O(nm)
, это s='a'*n
и p='a'*m+'ba'
.В этом случае последний символ p
равен 'a'
, поэтому первоначальная проверка проходит, но затем ему необходимо выполнить итерацию по оставшейся части p
, прежде чем он достигнет 'b'
.
# full='a'*n; sub='a'*m+'b'
>>> timeit("sub in full", "sub='a'*10+'b'; full='a'*100")
0.13620498299860628
>>> timeit("sub in full", "sub='a'*10+'b'; full='a'*1000")
0.9594046580004942
>>> timeit("sub in full", "sub='a'*100+'b'; full='a'*1000")
0.9768632190007338
# Linear in n, but m has minimal effect: ~O(n)
# full='a'*n; sub='a'*m+'ba'
>>> timeit("sub in full", "sub='a'*10+'ba'; full='a'*100")
0.35251976200015633
>>> timeit("sub in full", "sub='a'*10+'ba'; full='a'*1000")
3.4642483099996753
>>> timeit("sub in full", "sub='a'*100+'ba'; full='a'*1000")
27.152958754999418
# Both n and m have linear effect: ~O(nm)