Изменения

Перейти к: навигация, поиск

Префикс-функция

Нет изменений в размере, 18:38, 15 апреля 2012
Оптимизация
==Оптимизация==
Внесем несколько важных замечаний:
*<tex>\pi(i + 1)</tex> превосходит <tex>\pi(i-1)</tex> не больше чем на <tex>1</tex>. Действительно, если <tex>\pi(i+1) > \pi(i-1) + 1</tex>, тогда <tex>\pi(i+1) - 1 > \pi(i-1)</tex>, значит в <tex>\pi(i-1)</tex> не максимально возможное значение, получили противоречие.*Избавимся от явных сравнений строк. Пусть мы вычислили <tex>\pi(i-1)</tex> и <tex>s[\pi(i- 1) + 1] = s[i + 1]</tex>, тогда очевидно <tex>\pi(i+1) = \pi(i- 1) + 1</tex>. Если же условие <tex>s[\pi(i- 1) + 1] = s[i + 1]</tex> ложно, то хотелось бы найти наибольшую длину <tex> jk</tex>, для которой верно <tex>\pi(i+1) = j + 1k</tex>. Когда мы найдем такое <tex>jk</tex> нам достаточно будет сравнить <tex>s[j + 1k]</tex> и <tex>s[i + 1]</tex>, при их равенстве <tex>\pi(i+1) = j + 1k</tex> будет верно. Будем искать наше <tex>jk</tex> пока оно больше нуля, при равенстве нулю <tex>\pi(i+1) = 1</tex>, если <tex>s[i] = s[1]</tex>, иначе нулю. Общая схема алгоритма у нас есть, теперь нужно только научиться искать <tex>jk</tex>.*Для поиска <tex>jk</tex> нам стоит использовать равенство <tex>j k = \pi(jk - 1)+ 1</tex>, когда <tex>s[j+1k] = s[i+1]</tex> ложно, взяв за исходное <tex> j k = \pi(i- 1)+ 1</tex>, это позволит выбирать <tex>jk</tex> по убыванию вплоть до нуля, так как очевидно, что <tex>\pi(x) \geq \pi(\pi(x))</tex> для любых <tex>x</tex>.
===Псевдокод===
'''Prefix_function''' (<tex>s</tex>)
<tex>\pi</tex> = 0
'''for''' i = 2 '''to''' n
j = <tex>\pi</tex>[i - 1] + 1 '''while''' j > 0 && s[i] != s[j + 1] j = <tex>\pi</tex>[j- 1]+ 1
'''if''' s[i] == s[j + 1]
j++
304
правки

Навигация