Это решение (в Haskell) основано на наблюдении, что палиндром четной длины содержит повторяющийся символ в центре. Когда мы читаем символы из входного потока, мы проверяем такие пары, и когда они найдены, мы задаем новый ответ-кандидат. Для каждого палиндрома-кандидата мы также храним список «символов, оставшихся для сопоставления», и по мере чтения каждого нового символа мы сопоставляем его с этим списком — без совпадения кандидат отбрасывается. Когда список совпадений пуст, решение найдено. Обратите внимание, что хотя каждый кандидат поддерживает свой собственный список совпадений, все они являются просто суффиксами одного и того же списка, поэтому в Haskell все они будут совместно использовать пространство и в совокупности не будут занимать больше O(n) места, даже если существует много кандидатов.
В лучшем случае, когда в центре ответа находится только один парный символ и, следовательно, нет «ложноположительных» кандидатов, временная сложность равна O (n) — каждый символ проверяется не более двух раз. В случае входной строки со многими ложными запусками, т. Е. «abbbbbbbbbbbba», я не уверен во временной сложности — вероятно, это уже не O (n), но это лучше, чем O (n ^ 2), потому что ни один кандидат не живет дольше чем min(k, n-k)
, где k
— позиция центра кандидата.
filter_map::(a -> Maybe a)->[a]->[a]
filter_map op = foldr (maybeCons . op) []
where maybeCons Nothing ys = ys
maybeCons (Just y) ys = y:ys
-- Return the first prefix of the input argument that
-- is an even-length palindrome.
prefix_palindrome::(Eq a)=>[a]->[a]
prefix_palindrome (x:xs) = search [x] [] xs
where search seen ([]:_) _ = seen
search (s:seen) candidates (x:xs) | x == s = search seen' (candidates' ++ [seen]) xs
| otherwise = search seen' candidates' xs
where seen' = (x:s:seen)
candidates' = filter_map extend candidates
where extend (c:cs) | c == x = Just cs
| otherwise = Nothing
person
gcbenison
schedule
14.04.2012