Алгоритм на этом сайте кажется до некоторой степени понятным http://www.akalin.cx/longest-palindrome-linear-time
Чтобы понять этот конкретный подход, лучше всего попытаться решить проблему на бумаге и уловить уловки, которые вы можете реализовать, чтобы избежать проверки палиндрома для каждого возможного центра.
Сначала ответьте сами - когда вы найдете палиндром заданной длины, скажем, 5 - не можете ли вы в качестве следующего шага просто перейти к концу этого палиндрома (пропуская 4 буквы и 4 средних буквы)?
Если вы попытаетесь создать палиндром длиной 8 и разместить другой палиндром длиной> 8, центр которого находится справа от первого палиндрома, вы заметите что-то забавное. Попробуйте: палиндром длиной 8 - WOWILIKEEKIL - Like + ekiL = 8 Теперь в большинстве случаев вы можете записать место между двумя E как центр и число 8 как длину и перейти после последнего L, чтобы искать центр большего палиндрома.
Этот подход неверен, поскольку центр большего палиндрома может находиться внутри ekiL, и вы пропустите его, если прыгнете после последнего L.
После того, как вы найдете LIKE + EKIL, вы поместите 8 в массив, который используют эти алгоритмы, и это будет выглядеть так:
[0,1,0,3,0,1,0,1,0,3,0,1,0,1,0,1,8]
за
[#,W,#,O,#,W,#,I,#,L,#,I,#,K,#,E,#]
Хитрость в том, что вы уже знаете, что, скорее всего, следующие 7 (8-1) чисел после 8 будут такими же, как и слева, поэтому следующим шагом будет автоматическое копирование 7 чисел слева от 8 направо от 8, сохраняя помните, они еще не окончательные. Массив будет выглядеть так
[0,1,0,3,0,1,0,1,0,3,0,1,0,1,0,1,8,1,0,1,0,1,0,3] ( мы на 8)
за
[#,W,#,O,#,W,#,I,#,L,#,I,#,K,#,E,#,E,#,K,#,I,#,L]
Приведем пример, что такой скачок разрушит наше текущее решение, и посмотрим, что мы можем заметить.
WOWILIKEEKIL - давайте попробуем сделать палиндром побольше с центром где-нибудь внутри EKIL. Но это невозможно - нам нужно заменить слово EKIL на то, что содержит палиндром. Какие? ОООООх - вот и вся уловка. Единственная возможность иметь более крупный палиндром с центром в правой части нашего текущего палиндрома - это то, что он уже находится в правой (и левой) части палиндрома.
Давайте попробуем построить один на основе WOWILIKEEKIL. Нам нужно будет изменить EKIL, например, на EKIK, с I в качестве центра большого палиндрома - не забудьте также изменить LIKE на KIKE. Первыми буквами нашего хитрого палиндрома будут:
WOWIKIKEEKIK
как было сказано ранее - пусть последний я буду центром большего паллиндрома, чем КИКЕКИК:
WOWIKIKEEKIKEEKIKIW
давайте сделаем массив до нашего старого pallindrom и узнаем, как промыть дополнительную информацию.
за
[_ W _ O _ W _ I _ K _ I _ K _ E _ E _ K _ I _ K _ E _ E _ K _ I _ K _ I _ W ]
это будет [0,1,0,3,0,1,0,1,0,3,0,3,0,1,0,1,8
мы знаем, что следующий I - третий будет самым длинным паллиндромом, но давайте на время забудем об этом. позволяет скопировать числа в массиве слева от 8 вправо (8 чисел)
[0,1,0,3,0,1,0,1,0,3,0,3,0,1,0,1,8,1,0,1,0,3,0,3]
В нашем цикле мы находимся между буквами E с номером 8. Что особенного в I (будущая середина самого большого паллиндрома), что мы не можем перейти прямо к K (последней букве самого большого в настоящее время паллиндрома)? Особенность в том, что он превышает текущий размер массива ... как? Если вы переместите 3 пробела вправо от 3 - вы вне массива. Это означает, что это может быть середина самого большого паллиндрома, и дальше всего вы можете прыгнуть с этой буквы I.
Извините за длину этого ответа - я хотел объяснить алгоритм и могу вас заверить - @OmnipotentEntity был прав - я понял это даже лучше после объяснения вам :)
person
Jacek Serafinski
schedule
18.02.2013