【问题标题】:Ruby - Finding the longest palindromic substring in a stringRuby - 查找字符串中最长的回文子串
【发布时间】:2015-01-02 08:50:28
【问题描述】:

我知道如何判断一个字符串是否是回文

string1 == string1.reverse

虽然在一个字符串中有多个回文,但这有点困难

"abcdxyzyxabcdaaa"

在上面的字符串中,有4个长度大于1的回文

"xyzyx", "yzy", "aaa" and "aa"

在这种情况下,最长的回文是“xyxyx”,长度为 5 个字符。

我将如何解决这个问题。

我知道 array#combination 方法,但在这种情况下不起作用。

我正在考虑实现这样的东西

def longest_palindrome(string)
  palindromes = []
  for i in 2..string.length-1
    string.chars.each_cons(i).each {|x|palindromes.push(x) if x == x.reverse}
  end
  palindromes.map(&:join).max_by(&:length)
end

【问题讨论】:

标签: ruby string substring reverse palindrome


【解决方案1】:

如果您只是在寻找最大的回文子串,这里有一个快速而肮脏的解决方案。

def longest_palindrome(string, size)
  string.size.times do |start| # loop over the size of the string
    break if start + size > string.size # bounds check

    reverse = string[start, size].reverse

    if string.include? reverse #look for palindrome
      return reverse #return the largest palindrome
    end
  end
  longest_palindrome(string, size - 1) # Palindrome not found, lets look for the next smallest size 
end

【讨论】:

  • 出色且经过深思熟虑的解决方案。那会奏效的。
  • 这是不正确的 - longest_palindrome('abcdefghba', 10) 返回 'ba' 这是不正确的。包含条件不够。
  • 您错过了回文的实际检查...if string[start, size].reverse == string[start, size]
【解决方案2】:

这是另一种解决方案,使用 Ruby 的较少功能和迭代而不是递归:

def longest_palindrome(string)
  # to find the longest palindrome, start with whole thing
  substr_start = 0
  substr_length = string.length
  while substr_length > 0 # 1 is a trivial palindrome and the end case
#    puts 'substr_length is:' + substr_length.to_s
    while substr_start <= string.length - substr_length
#      puts 'start is: ' + substr_start.to_s
      if palindrome?(string.slice(substr_start,substr_length))
        puts 'found palindrome: ' + string.slice(substr_start,substr_length)
        return string.slice(substr_start,substr_length)
      end
      substr_start += 1
    end
    substr_start = 0 # inner loop ctr reset
    substr_length -= 1
  end
  puts 'null string tested?'
  return ''
end

【讨论】:

    【解决方案3】:

    这会检查整个字符串 str 是否是回文。如果是,我们就完成了;如果不是,请检查所有长度为str.size-1 的子字符串。如果一个是回文,我们就完了;如果不是,检查长度为str.size-1 的子串,依此类推。

    def longest_palindrome(str)
      arr = str.downcase.chars
      str.length.downto(1) do |n|
        ana = arr.each_cons(n).find { |b| b == b.reverse }
        return ana.join if ana
      end
    end
    
    longest_palindrome "abcdxyzyxabcdaaa"
      #=> "xyzyx"
    longest_palindrome "abcdefghba"
      #=> "a"
    

    这里的关键方法是Enumerable#each_cons

    【讨论】:

      【解决方案4】:
      def longest_palindrome(string)
        longest = ''
        i = 0
        while i < string.length
          j = 1
          while (i + j) <= string.length
            x = string.slice(i, j)
            if (x.length > longest.length) && (x == x.reverse)
              longest = x
            end
            j += 1
          end
          i += 1
        end
        longest
      end
      

      切片方法可以很方便地解决这个问题。使用经典的双 while 循环方法测试每个子字符串,(i, j) 分别代表子字符串的起始索引和长度。 string.slice(start_index, substring_length)

      String#slice 方法的工作原理如下:

      "bdehannahc".slice(3, 8) == "hannah" # which is a palindrome and would be 
                                           # found by the method introduced above
      

      【讨论】:

        猜你喜欢
        • 2016-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多