计算二进制字符串

时间:2012-07-15 02:55:09

标签: algorithm

这是针对this问题。我们需要计算f(n,k),它是长度为n的二进制字符串的数量,其长度为1的最长子字符串的长度为k。我在提交递归时遇到了麻烦。

当第i位为0时,我认为我可以处理。 具体来说,当我将第i个数字视为1时,我无法将解决方案扩展到子问题f(i-1,j)。如何将两者拼接在一起?

很抱歉,如果我有点不清楚。任何指针都会有很大的帮助。感谢。

3 个答案:

答案 0 :(得分:1)

我认为如果扩展状态空间,可以使用动态编程的变体来构建表。假设您计算f(n,k,e)定义为长度为n的不同二进制字符串的数量,最长子串为1s长度最多为k且以行中的e 1结尾。如果你计算了与给定n相关的k和e的所有可能值的f(n,k,e),那么,因为你有e分割的值,你可以计算f(n + 1,k,e) )对于k和e的所有可能值 - 当你用0或1扩展它时,n长字符串会发生什么情况取决于它此刻结束的数量为1,并且你知道因为e。

答案 1 :(得分:1)

设s是长度 k 模式的起始索引。然后s在:1到n-k。

对于每个s,我们将Sting S分成三个字符串:

PRE(s,k,n) = S[1:s-1] 
POST(s,k,n)=S[s+k-1:n] 
ONE(s,k,n) which has all 1s from S[s] to S[s+k-1]

PRE和POST的最长1s子串应小于k。

x = s-1 
y = n-(s+k)-1

设NS(p,k)是总长度大于等于k的子串的方式。

NS(p,k) = sum{f(p,k), f(p,k+1),... f(p,p)} 

终止条件:

NS(p,k) = 1 if p==k, 0 if k>p
f(n,k) = 1 if n==k, 0, if k > n.

对于长度为n的字符串,排列的数量使得1s的最长子字符串的大小小于k = 2 ^ n - NS(n,k)。

f(n,k) = Sum over all s=1 to n-k 
         {2^x - NS(x,k)}*{2^y - NS(y,k)}

即。每个前后子串的排列数的乘积,其中最长的子串小于大小k。

所以我们有一个重复的子问题,以及一大堆可以DPed的重用

稍后添加: 根据下面的评论,我想我们真的不需要进入NS。 我们可以将S(p,k)定义为

S(p,k) = sum{f(p,1), f(p,2),... f(p,k-1)} 

f(n,k) = Sum over all s=1 to n-k 
         S(x,k)*S(y,k)

答案 2 :(得分:0)

我知道这是一个很老的问题,如果有人想要我可以澄清我的小答案..

这是我的代码

#include<bits/stdc++.h>
using namespace std;
long long DP[64][64];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,k;
    DP[1][0]=1;
    DP[1][1]=1;
    DP[0][0]=1;
    cout<<"1 1\n";
    for(i=2;i<=63;i++,cout<<"\n")
        {
            DP[i][0]=1;
            DP[i][i]=1;
            cout<<"1 ";
            for(j=1;j<i;j++)
            {
                for(k=0;k<=j;k++)
                    DP[i][j]+=DP[i-k-1][j]+DP[i-j-1][k];
                DP[i][j]-=DP[i-j-1][j];
                cout<<DP[i][j]<<" ";
            }
            cout<<"1 ";
        }
    return 0;
}

DP [i] [j]代表F(i,j)。

过渡/重现(难以思考):

考虑F(i,j):

1)我可以在右边放k 1s并用0分开它们  字符串+ 0 + k次&#39; 1&#39; 。 F(I-K-1,j)的 注意:k = 0表示我只在右边保持0!

2)我错过了正确的j + 1位置填充0和j&#39; 1&#39; s和所有左边不形成任何连续的长度为j的字符串!! F(i-j-1,k)(注意我用k代表两者都是因为我在我的代码中已经这样做了,你也可以定义其他变量!)