2010-09-30 94 views
3

如何找到O(n)中字符串的最长回文前缀?最长的回文前缀

+3

这听起来像一个家庭作业的问题。如果是这样,它应该被标记为这样。 – 2010-09-30 17:18:56

+1

定义最长的回文前缀。而且时间应该由O(n)还是记忆来约束呢?这是作业吗? – 2010-09-30 17:20:00

+1

我觉得这个答案是丰田 – 2010-09-30 18:24:12

回答

1

解决方案更普遍的问题,而不是前缀,而子串,在O(N):

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

在谷歌第二个结果为 “最长回文前缀” ......

或使用的解决方案后缀树:

http://www.allisons.org/ll/AlgDS/Tree/Suffix/

+0

在链接到akalin.cx的函数中有'fastLongestPalindromes(..)'实际上'O(n)'最坏情况的复杂度?我看到两个嵌套循环.. – 2010-10-01 20:01:22

+0

没有读取所有内容,但是2个嵌套循环并不意味着二次复杂性。函数开始处的继续应确保仅在少数情况下执行内部循环,并且该循环的每次执行的总体复杂度为O(n)。 – 2010-10-01 21:31:01

5

使用rolling hash。如果a是您的字符串,则让ha[x]成为从左到右计算的a中第一个x个字符的散列,并且让hr[x]成为s中从头到尾计算的第一个x个字符的散列。您对i的最后位置感兴趣,其中hf[i] = hb[i]。用C

代码(使用两个散列每个方向,以避免假阳性):

int match = n - 1; 

int ha1 = 0, ha2 = 0, hr1 = 0, hr2 = 0; 
int m1 = 1, m2 = 1; 
for (int i = 0; a[i]; ++i) 
{ 
    ha1 = (ha1 + m1*a[i]) % mod1; 
    ha2 = (ha2 + m2*a[i]) % mod2; 

    hr1 = (a[i] + base1*hr1) % mod1; 
    hr2 = (a[i] + base2*hr2) % mod2; 

    m1 *= base1, m1 %= mod1; 
    m2 *= base2, m2 %= mod2; 

    if (ha1 == hr1 && ha2 == hr2) 
     match = i; 
} 
+0

我认为'从右到左'的部分在代码示例中不存在...('i'从左到右,只能访问'a [i]'。 – 2010-09-30 21:38:00

+0

@Andre Holzner - '我'只从左到右,在每一步'i',你将有''匹配'存储当前最长的回文前缀的长度。只有滚动哈希是双向的。 – IVlad 2010-09-30 21:51:51

+0

+1,我didn'我知道它被称为'滚动哈希',但我甚至有两次哈希并不能保证每个肯定都是'真实的'(更不用说,用这样不寻常的系数:))。简单地说,因为在某些长度_n_中,比不同对的int数字_(ha1,ha2)_有更多的n个字符的字符串。如果你确认每一个都是肯定的,你会在统一字符串('aaaaaaaa ...')上得到O(n^2)。 – 2010-09-30 23:50:27