计算O(n)中的回文子串

时间:2010-09-05 19:31:34

标签: algorithm string optimization count

给定长度为S的字符串(仅假设英文字符)n,我们可以使用以下算法计算回文子串的数量:

for i = 0 to |S| do
    p1 = number of palindromes centered in i (odd length)
    p2 = number of palindromes centered in i and i+1 (even length)

    add p1 + p2 to total number of palindromic substrings of S

上面的代码是O(n^2)

我对在O(n)中解决此问题的算法感兴趣。我肯定知道有一个存在,因为我听到有多个人说它确实存在,并且问题存在于1 000 000的{​​{1}}上限的本地在线评判网站上,但是我已经从未见过算法,似乎无法想出它。

更新

我的一般想法是为偶数长度的回文计算n和类似的数组。通过良好的簿记,应该可以在len[i] = length of the longest palindrome centered at the character 2i + 1中为每个角色计算一次,这样我们就可以同时计算很多回文。然而,我仍然坚持如何计算这一点。

我会接受使用O(1)甚至O(n)额外内存的解决方案。我想如果没有它,这是不可能的。

赞赏任何好的想法或参考。

3 个答案:

答案 0 :(得分:7)

以下网站显示了在O(n)时间内计算最长回文子串的算法,并通过计算每个可能中心的最长回文子串然后取最大值来实现。因此,您应该可以根据自己的需要轻松修改它。

http://www.akalin.cx/2007/11/28/finding-the-longest-palindromic-substring-in-linear-time/

编辑:经过仔细检查,第一个链接看起来有些不稳定,所以这是另一个链接:

http://zhuhcheng.spaces.live.com/Blog/cns!DE38E96268C49F28!311.entry?wa=wsignin1.0&sa=707413829

答案 1 :(得分:1)

对于“普通”字符串,将每个字符视为回文的潜在“中心”然后检查周围的字符是否实际构建一个字符应该是相当有效的:

# check odd palindromes
for center in range(len(ls)):
   # check how many characters to the left and right of |center|
   # build a palindrome
   maxoffs = min(center, len(ls)-center-1)
   offs = 0
   while offs <= maxoffs and ls[center-offs] == ls[center+offs]:
      offs += 1
   offs -= 1
   print ls[center-offs : center+offs+1]                                    

# check for even palindromes
for center in range(len(ls)-1):
   maxoffs = min(center, len(ls)-center-2)
   offs = 0
   while offs <= maxoffs and ls[center-offs] == ls[center+offs+1]:
      offs += 1
   offs -= 1
   if offs >= 0:
      print ls[center-offs : center+offs+2]

对于普通字符串,这应该是O(n),尽管在最坏的情况下,例如,如果字符串只包含一个重复的一个字符,它仍然需要O(n 2

答案 2 :(得分:1)

考虑一个字符串S="aaabb"

在字符串的两端和每两个连续字符之间附加一个字符'$',将字符串更改为S="$a$a$a$b$b$",并为此字符串S应用Manacher's algorithm

新字符串S的长度为2n + 1,它为运行时提供O(2n + 1),与O(n)相同。

index :  1 2 3 4 5 6 7 8 9 10 11
A     :  1 3 5 7 5 3 1 3 5  3  1
S     :  $ a $ a $ a $ b $  b  $

数组A是Manacher算法的结果。

现在,A[i]/4的索引总和为'$',其他(A[i]+1)/4为1&lt; = i&lt; = n的每个其他字符的答案。

这里,$充当偶数长度的悬崖子串的中心,奇数长度可以正常计算。这个案子的答案是:

  

0 + 1 + 1 + 2 + 1 + 1 + 0 + 1 + 1 + 1 + 0 = 9(a,a,aaa,a,b,b,aa,aa,bb)。