最长回文子串和后缀特里树

Posted

技术标签:

【中文标题】最长回文子串和后缀特里树【英文标题】:Longest palindromic substring and suffix trie 【发布时间】:2012-05-26 16:20:25 【问题描述】:

我在谷歌上搜索一个相当知名的问题,即:the longest palindromic substring 我发现推荐后缀尝试的链接是解决问题的好方法。 示例 SO 和 Algos 方法是(据我了解)例如对于字符串 S 创建 Sr (这是 S 反转),然后创建一个通用的后缀 trie。 然后找到SSr的最长公共子串,这是从根到最深节点的路径,同时属于SSr。 因此,使用后缀尝试方法的解决方案本质上简化为Find the longest common substring 问题。 我的问题如下: 如果输入字符串是:S = “abacdfgdcaba” so ,Sr = “abacdgfdcaba” 最长的公共子字符串是 abacd,它不是回文。 所以我的问题是:使用后缀尝试的方法是否错误?我在这里误解/误读了吗?

【问题讨论】:

【参考方案1】:

是的,使用类似 LCS 的算法找到最长回文不是一个好方法,我没有仔细阅读参考答案,但答案中的这一行是完全错误的:

所以一个字符串中最长包含的回文正好是这个字符串的最长公共子串和它的倒序

但是如果你读过它并且你有一个反例不要担心它(你在 99% 中是对的),这是常见的错误,但简单的方法如下:

写下字符串(barbapapa)如下:#b#a#r#b#a#p#a#p#a#,现在从左到右遍历这个新字符串的每个字符,检查它的左右是否是回文中心。这个算法在最坏的情况下是 O(n^2) 并且完全正确。但通常会在 O(n) 中找到回文(确保在一般情况下很难证明这一点)。最坏的情况是包含太多长回文的字符串,例如aaaaaa...aaaa

但是有更好的方法需要 O(n) 时间,这个算法的基础是Manacher。相关算法比我在您引用的答案中看到的更复杂。但我提供的是 Manacher 算法的基本思想,通过巧妙地更改算法,您可以跳过检查所有左右(也有使用后缀树的算法)。


P.S:由于我的互联网限制,我无法看到您的 Algo 链接,我不知道它是否正确。

我添加了与 OP 的讨论以阐明算法:

let test it with barbapapa-> #b#a#r#b#a#p#a#p#a#, start from first #
there is no left so it's center of palindrome with length 1.
Now "b",has # in left and # in right, but there isn't another left to match with right 
so it's a center of palindrome with length 3.
let skip other parts to arrive to first "p":
first left and right is # second left and right is "a", third left and
right is # but forth left and right are not equal so it's center of palindrome
of length 7 #a#p#a# is palindrome but b#a#p#a#p is not 
Now let see first "a" after first "p" you have, #a#p#a#p#a# as palindrome and this "a" 
is center of this palindrome with length 11 if you calculate all other palindromes 
length of all of them are smaller than 11

还使用# 是因为考虑了偶数长度的回文。

在新创建的字符串中找到回文的中心后,找到相关的回文(通过知道中心及其长度),然后删除#以找出最大的回文。

【讨论】:

also there are algorithms by using suffix trees 这部分我不明白。这不是我的操作吗?我的意思是,如果我们使用后缀树,那将是为了使用SSr 的通用后缀树通过SSr 找到最长的公共子字符串。所以我们最终解决了我原来的问题。那你在这里是什么意思? @user384706,实际上我不知道他们如何使用后缀树,我之前读过 Manacher 的算法,但我知道所有其他算法都是对 Manacher 算法的改进,使其更容易和更有用,我不认为相关的后缀树算法正在使用(S,Sr),但我不确定。但是您提到的答案是错误,另外,如果您对回文中的后缀树用法更感兴趣,您应该阅读相关论文(不是不确定的链接),您可以在我引用的 wiki 页面上找到它们(如果您可以下载它们,我也认为您可以在网络上免费找到它们。 @user384706:用于寻找偶数长度的回文,例如:aaaaas 中的哪一个会是最长回文的中心?没有一个,但在a#a#a#a,第二个#是原始字符串中最长回文的中心(我在开头和结尾写得很尖锐,但它们是多余的,只是为了让这个词更漂亮;) 但是在这种情况下,奇数长度呢?即aaa 变为 #a#a#a#。所以现在中心是第二个 a。不是# @user384706,是的,中心是第二个a,实际上如果回文长度是偶数,中心将是#,但在奇数情况下,原始字符是回文的中心。找到最大回文的中心后,您可以提取原始回文。 (为了找到最大的回文,只需在迭代过程中保存最大回文中心的长度和位置就足够了)。

以上是关于最长回文子串和后缀特里树的主要内容,如果未能解决你的问题,请参考以下文章

动态规划:最长回文子串和子序列

ural1297(后缀树组+rmq)

Leetcode篇:最长回文子串

算法最长回文子串 longest palindrome substring

华为机试题 HJ85最长回文子串

华为机试题 HJ85最长回文子串