如何避免生成所有子序列

时间:2012-06-28 09:37:02

标签: algorithm dynamic-programming

  

可能重复:
  Square Subsequence

我一直在尝试解决interviewstreet.com上的“Square Subsequences”问题:

  

如果可以通过连接相同字符串的两个副本来获取字符串,则将其称为方形字符串。例如,“abab”,“aa”是方形字符串,而“aaa”,“abba”则不是。

     

给定一个字符串,该字符串的子序列有多少是方形字符串?

我尝试制定DP解决方案,但这种约束似乎无法规避:S will have at most 200 lowercase characters (a-z)

据我所知,查找长度为n的列表的所有子序列为 O(2^n) ,一旦n大于n,就会停止可行比方说,30。

如果{{1}}为200,是否真的可以系统地检查所有解决方案?我该如何处理?

2 个答案:

答案 0 :(得分:3)

首先,对于每个字母a..z,您都会在S中获得其索引列表:

`p[x] = {i : S[i] = x}`, where `x = 'a',..,'z'`.

然后我们开始DP:

S: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            ^          ^    ^
            r1        l2    r2

f(r1,l2,r2)为任意长度L平方子序列(方形字符串的子序列)的数量,以便

  1. SS[L-1] = r1
  2. SS[L] = l2
  3. SS[2L-1] = r2
  4. 即。前半部分正好在r1结束,后半部分恰好在l2开始,到r2结束。

    然后算法:

    如果f[r1,l2,l2] = 1,则S[r1] = S[l2],否则为0。

    for (l2 in 1..2L-1 )
        for( r1 in 0..l2-1 )
            for (r2 in l2..2L-1)
                if( f(r1, l2, r2) != 0 )
                    for (x in 'a'..'z')
                        for (i,j: r1 < i < l2, r2 < j, S[i] = S[j] = x) // these i,j are found using p[x] quickly
                            f[i, l2, j] += f[r1, l2, r2]
    

    最后,答案是f[.,.,.]数组中所有值的总和。

    基本上,我们将S unisg l2分为两部分,然后计算公共子序列。

    我现在很难提供准确的时间复杂度估算,n^4以下n^4n = 200可以接受{{1}}。

答案 1 :(得分:0)

有许多算法(例如Z-algorithm)可以在线性时间内生成前缀长度数组。这是针对每个位置我告诉你从位置i开始可以读取的最长前缀是什么(当然i = 0,longetst前缀是n)。

现在注意,如果你从头开始有一个方形字符串,那么在这个前缀长度数组中有一个位置k,使得最长的长度是> = k。因此,您可以再次计算线性时间的数量。

然后删除你字符串的第一个字母并做同样的事情。 其总复杂度为O(n ^ 2)。