Algorithm 计算二进制字符串

Algorithm 计算二进制字符串,algorithm,Algorithm,这是关于这个问题的。我们需要计算f(n,k),它是长度为n的二进制字符串的数量,其中最长的子字符串的长度为k。我很难想出一个递归 如果第i个数字是0,我想我可以处理。 具体来说,当我认为第i个数字为1时,我无法将该解扩展到子问题f(i-1,j)。我怎么把这两个缝在一起 对不起,如果我有点不清楚。任何指点都会有很大的帮助。谢谢。如果扩展状态空间,我认为可以使用动态规划的一种变体来建立一个表。假设计算f(n,k,e),定义为长度为n的不同二进制字符串的数量,其中最长的子字符串长度为1s,最大长度为k

这是关于这个问题的。我们需要计算f(n,k),它是长度为n的二进制字符串的数量,其中最长的子字符串的长度为k。我很难想出一个递归

如果第i个数字是0,我想我可以处理。 具体来说,当我认为第i个数字为1时,我无法将该解扩展到子问题f(i-1,j)。我怎么把这两个缝在一起


对不起,如果我有点不清楚。任何指点都会有很大的帮助。谢谢。

如果扩展状态空间,我认为可以使用动态规划的一种变体来建立一个表。假设计算f(n,k,e),定义为长度为n的不同二进制字符串的数量,其中最长的子字符串长度为1s,最大长度为k,并以行中的e1s结尾。如果你已经计算了与给定n相关的k和e的所有可能值的f(n,k,e),那么,因为这些值被e分割,你可以计算k和e的所有可能值的f(n+1,k,e)-当你用0或1扩展一个n长的字符串时,它会发生什么,这取决于它此时结束的1s数,你知道,因为e.

让我们作为长度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]
前置和后置的最长子串1s应小于k

设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)的排列数

i、 e.最长子串小于大小k的每个前置子串和后置子串的排列数的乘积

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

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


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

这是我的密码

#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;
}
#包括
使用名称空间std;
long-long-DP[64][64];
int main()
{
ios::将_与_stdio同步(0);
cin.tie(0);
int i,j,k;
DP[1][0]=1;
DP[1][1]=1;
DP[0][0]=1;

我只定义了N和K.0i还没有真正解决这个问题,但是我建议你考虑二进制数的替代表示。想到的是一个列表,它指示开始时的个数,之后的0个数,之后的数,等等。我不知道这个想法会有什么帮助。我将尝试在纸上解决一些问题。如果想到递归公式,请发帖。谢谢。dfeuer的建议有一个很好的建议:你可以通过这种方式将这些字符串与整数组合相关联。我喜欢你如何开始这项工作,但为什么你要计算出错的方式而不是正确的方式?是的,我有一个他提出了另一种方法。
f(n,k) = Sum over all s=1 to n-k 
         {2^x - NS(x,k)}*{2^y - NS(y,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)
#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;
}