Skip to content

Instantly share code, notes, and snippets.

@cstump
Last active August 29, 2015 14:25
Show Gist options
  • Select an option

  • Save cstump/8885d6d33e21333e56ff to your computer and use it in GitHub Desktop.

Select an option

Save cstump/8885d6d33e21333e56ff to your computer and use it in GitHub Desktop.
Find the longest palindrome in a string
#
# Finds the longest palindrome in a string
# Works for palindromes of both even and odd length
# Has O(n^2) runtime, which is not the fastest
# Manacher's algorithm promises O(n) time
#
# Odd length example: "ABCBAHELLOHOWRACECARAREYOUILOVEUEVOLIIAMAIDOINGGOOD"
# Result: 'ILOVEUEVOLI'
#
# Even length example: "forgeeksskeegfor"
# Result: 'geeksskeeg'
class PalindromeFinder
PAD_CHAR = '#'
attr_accessor :string, :results
def initialize(string)
self.results = {}
self.string = string
transform_string if even_string?
end
def find_longest
string.chars.each_with_index do |char, i|
matches = 0
step_from_center = 1
while match?(i, step_from_center)
matches += 1
step_from_center += 1
end
results[i] = matches
end
output_longest
end
private
def even_string?
string.size % 2 == 0
end
def transform_string
self.string = string.chars.map{|c| [c, PAD_CHAR] }.flatten.unshift(PAD_CHAR).join
end
def match?(i, step_from_center)
left_ndx = i - step_from_center
right_ndx = i + step_from_center
left_ndx >= 0 && right_ndx < string.size && string[left_ndx] == string[right_ndx]
end
def longest_result
@longest_result ||= results.max{|r1, r2| r1[1] <=> r2[1] }
end
def output_longest
start_char = longest_result[0] - longest_result[1]
end_char = longest_result[0] + longest_result[1]
palindrome = string[start_char..end_char]
palindrome.gsub!(PAD_CHAR, '') if palindrome.include?(PAD_CHAR)
puts "The longest palindrome is '#{palindrome}'"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment