Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何避免生成所有子序列_Algorithm_Dynamic Programming - Fatal编程技术网

Algorithm 如何避免生成所有子序列

Algorithm 如何避免生成所有子序列,algorithm,dynamic-programming,Algorithm,Dynamic Programming,可能重复: 我一直在努力解决interviewstreet.com上的“”问题: 如果一个字符串可以通过连接同一字符串的两个副本来获得,则该字符串称为方形字符串。例如,“abab”、“aa”是方字符串,“aaa”、“abba”不是 给定一个字符串,该字符串有多少子序列是方字符串? 我尝试了一个DP解决方案,但这个约束似乎无法绕过:S最多有200个小写字符(a-z) 据我所知,查找长度n的列表的所有子序列是O(2^n),一旦n大于,比如说30,它就不再可行 如果n为200,是否真的可以系统地检查

可能重复:

我一直在努力解决interviewstreet.com上的“”问题:

如果一个字符串可以通过连接同一字符串的两个副本来获得,则该字符串称为方形字符串。例如,“abab”、“aa”是方字符串,“aaa”、“abba”不是

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

我尝试了一个DP解决方案,但这个约束似乎无法绕过:
S最多有200个小写字符(a-z)

据我所知,查找长度
n
的列表的所有子序列是
O(2^n)
,一旦
n
大于,比如说30,它就不再可行

如果
n
为200,是否真的可以系统地检查所有解决方案?如何处理它?

有许多算法(例如)可以在线性时间内生成前缀长度数组。也就是说,对于每个位置i,它告诉您从位置i开始可以读取的最长前缀是什么(当然,对于i=0,最长前缀是n)

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

然后删除字符串的第一个字母并执行相同的操作。
这个问题的总复杂度为O(n^2)。

首先,对于每个字母
a..z
,您将在
S
中获得它们的索引列表:

`p[x] = {i : S[i] = x}`, where `x = 'a',..,'z'`.
然后我们开始DP:

S: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            ^          ^    ^
            r1        l2    r2
f(r1,l2,r2)
为任意长度
L
的平方子序列(为方字符串的子序列)的数量

  • SS[L-1]=r1
  • SS[L]=l2
  • SS[2L-1]=r2
  • i、 e.前半部分正好在
    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]
    
    for(1..2L-1中的l2)
    对于(0..l2-1中的r1)
    用于(l2..2L-1中的r2)
    如果(f(r1,l2,r2)!=0)
    对于(a'中的x…'z')
    对于(i,j:r1
    最后,答案是
    f[,,.]
    数组中所有值的总和

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


    我现在很难提供准确的时间复杂度估计,它肯定低于
    n^4
    ,并且
    n^4
    对于
    n=200

    是可以接受的,但请注意,问题是要求子序列,而不是子字符串。例如,
    baba
    包含3个方形子序列(
    baba
    bb
    aa
    )。这也是一次面试,当然没人希望别人在面试中实现Z。interviewstreet.com不是面试lol:-)是的,你说得对。谢谢。同时我也发现了,所以我将检查它的复杂性。我现在没有足够的代表(
    =15
    )来投票。@Dilbert,是的,很好,我认为这个答案有完全相同的想法,但它省略了“如何在给定的段中有效地找到相等的字母对”部分:我使用
    p[x]
    为此,你甚至可以在
    p[x]
    中使用二进制搜索。第二个:这个解决方案对数组还有一个维度:第一个序列的开始,这对我来说似乎是不必要的:它将时间和空间复杂度再乘以
    n
    一次,这让它变得悲观(我不相信,它太粗糙了)
    n^6
    @Dilbert,好的,
    n^4
    现在。+1但200^4不是那么小。C#的时间限制是5秒,在我的1.6Ghz Core2duo上做一次200^4倍的乘法大约需要8秒,所以即使它能通过他们的测试,也将是一个非常接近的过程。我相信应该有一个时间复杂度更低的解决方案。@Dilbert,是的,有一个
    n^3
    解决方案,也许我以后会编辑。你应该在问题中说明时间限制。请你将问题链接起来!