返回

算法入门:最长回文子串的寻找之旅

见解分享

踏入算法世界,寻觅回文子串的足迹

算法,是计算机科学的核心领域之一,它为解决复杂问题提供了系统的方法和步骤。在算法世界中,回文子串的查找是一个经典且有趣的问题,它不仅考验算法设计者的智慧,也对编程技巧提出了不小的要求。

回文子串,是指一个字符串从左到右读和从右到左读都一样的子字符串。例如,字符串“abba”中的“abba”和“bb”都是回文子串。在现实世界中,回文子串的应用十分广泛,从DNA序列分析到文本处理,再到密码学,回文子串的身影无处不在。

初探回文子串的奥秘

在探索回文子串之前,我们首先需要了解它的基本概念和性质。

  • 回文子串可以是单个字符,也可以是多个字符组成的字符串。
  • 回文子串不一定是从字符串的开头到结尾,它可以出现在字符串的任意位置。
  • 回文子串可以嵌套在另一个回文子串中。例如,在字符串“abbaabba”中,“abba”是回文子串,“bb”也是回文子串,而“abbaabba”本身也是一个回文子串。

穷举法:朴素而直接的解题思路

面对回文子串的查找问题,最直接的想法莫过于穷举法。穷举法,顾名思义,就是枚举所有可能的子字符串,然后逐一检查它们是否为回文子串。这种方法虽然简单易懂,但时间复杂度却非常高,对于较长的字符串,穷举法几乎是不可行的。

穷举法的算法流程如下:

  1. 对于字符串中的每个字符,依次枚举所有长度从1到字符串长度的子字符串。
  2. 检查每个子字符串是否为回文子串。
  3. 记录最长的回文子串及其位置。

穷举法的Python代码实现如下:

def longest_palindrome_naive(string):
  """
  Finds the longest palindrome in a given string using the naive approach.

  Args:
    string: The string to search.

  Returns:
    The longest palindrome in the string.
  """

  # Initialize the longest palindrome and its length.
  longest_palindrome = ""
  longest_length = 0

  # Iterate over the string.
  for i in range(len(string)):
    # Iterate over all possible substring lengths.
    for j in range(i + 1, len(string) + 1):
      # Check if the substring is a palindrome.
      substring = string[i:j]
      if substring == substring[::-1]:
        # If the substring is a palindrome, update the longest palindrome and its length.
        if len(substring) > longest_length:
          longest_palindrome = substring
          longest_length = len(substring)

  return longest_palindrome


# Example usage.
string = "abba"
longest_palindrome = longest_palindrome_naive(string)
print(f"The longest palindrome in '{string}' is '{longest_palindrome}'.")

中心扩展法:高效而优雅的算法设计

穷举法虽然简单,但时间复杂度却非常高。为了解决这个问题,我们引入了一种更有效率的算法——中心扩展法。中心扩展法的基本思想是,对于字符串中的每个字符,将其作为回文子串的中心,然后向两边扩展,检查字符串是否对称。如果字符串对称,则该中心字符及其左右对称的字符组成了一个回文子串。

中心扩展法的算法流程如下:

  1. 对于字符串中的每个字符,依次将其作为回文子串的中心。
  2. 从中心向两边扩展,检查字符串是否对称。
  3. 记录最长的回文子串及其位置。

中心扩展法的Python代码实现如下:

def longest_palindrome_center_expansion(string):
  """
  Finds the longest palindrome in a given string using the center expansion approach.

  Args:
    string: The string to search.

  Returns:
    The longest palindrome in the string.
  """

  # Initialize the longest palindrome and its length.
  longest_palindrome = ""
  longest_length = 0

  # Iterate over the string.
  for i in range(len(string)):
    # Expand around the center character.
    left = i
    right = i
    while left >= 0 and right < len(string) and string[left] == string[right]:
      # If the substring is a palindrome, update the longest palindrome and its length.
      if right - left + 1 > longest_length:
        longest_palindrome = string[left:right + 1]
        longest_length = right - left + 1
      # Expand the palindrome.
      left -= 1
      right += 1

    # Expand around the center of two adjacent characters.
    left = i
    right = i + 1
    while left >= 0 and right < len(string) and string[left] == string[right]:
      # If the substring is a palindrome, update the longest palindrome and its length.
      if right - left + 1 > longest_length:
        longest_palindrome = string[left:right + 1]
        longest_length = right - left + 1
      # Expand the palindrome.
      left -= 1
      right += 1

  return longest_palindrome


# Example usage.
string = "abba"
longest_palindrome = longest_palindrome_center_expansion(string)
print(f"The longest palindrome in '{string}' is '{longest_palindrome}'.")

马拉车算法:性能更优的回文查找利器

中心扩展法虽然已经非常高效,但对于非常长的字符串,它的时间复杂度仍然较高。为了进一步提高回文子串查找的性能,我们可以引入马拉车算法。马拉车算法是一种基于动态规划的算法,它通过计算每个子字符串是否是回文子串来构建一个动态规划表。然后,我们可以通过查询动态规划表来快速找到最长的回文子串。

马拉车算法的Python代码实现如下:

def longest_palindrome_manacher(string):
  """
  Finds the longest palindrome in a given string using the Manacher's algorithm.

  Args:
    string: The string to search.

  Returns:
    The longest palindrome in the string.
  """

  # Preprocess the string.
  preprocessed_string = "#" + "#".join(string) + "#"

  # Initialize the longest palindrome and its length.
  longest_palindrome = ""
  longest_length = 0

  # Create the dynamic programming table.
  dp = [0] * len(preprocessed_string)

  # Find the center and right boundary of the longest palindrome.
  center = 0
  right = 0

  # Iterate over the preprocessed string.
  for i in range(1, len(preprocessed_string)):
    # Mirror index.
    mirror_index = 2 * center - i

    # Check if the mirror index is within the right boundary.
    if i < right:
      # Copy the palindrome length from the mirror index.
      dp[i] = min(dp[mirror_index], right - i)

    # Expand the palindrome.
    while i + dp[i] < len(preprocessed_string) and i - dp[i] >= 0 and preprocessed_string[i + dp[i]] == preprocessed_string[i - dp[i]]:
      dp[i] += 1

    # Update the center and right boundary of the longest palindrome.
    if i + dp[i] > right:
      center = i
      right = i + dp[i]

    # Update the longest palindrome.
    if dp[i] > longest_length:
      longest_palindrome = preprocessed_string[i - dp[i]:i + dp[i]]
      longest_length = dp[i]

  # Return the longest palindrome.
  return longest_palindrome[1:-1:2]


# Example usage.
string = "abba"
longest_palindrome = longest_palindrome_manacher(string)
print(f"The longest palindrome in '{string}' is '{longest_palindrome}'.")

结语

回文子串的查找是一个经典的算法问题,它不仅考验算法设计者的智慧,也对编程技巧提出了不小的要求。在本文中,我们介绍了三种不同的回文子串查找算法,分别是穷举法、中心扩展法和