动态规划作业-最长公共子序列问题

问题:对给定序列X=(x1,x2,...xm)和序列Z=(z1,z2,...zk),Z是X的子序列当且仅当存在一个递增下标序列(i1,i2,...ik)

          使得对于所有j=1,2,,,k有zj=xij(1<=xij<=m)。例如序列(a,b,c,b,d,a,b)的一个子序列(b,c,d,b)

          相应的递增下标序列(2,3,5,7)

          给定两个序列X和Y,当序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列

定义子问题:设L(m,n)表示序列X=(x1,x2,...xm和Y=(y1,y2,...yn)的最长公共子序列的长度,显然

                      初始子问题是序列X和Y至少有一个空序列,即:

                      L(0,0)=L(0,j)=L(i,0)=0,     1<=i<=m,1<=j<=n

动态规划函数:

                      L(i,j)=L(i-1,j-1)+1                 xi=yj,i>=1,j>=1

                      L(i,j)=max{(L(i-1,j),L(i,j-1)}   xi!=yj,i>=1,j>=1

为了得到序列X和Y的最长公共子序列,设二维表S(m,n)记载求解过程中的状态变化

                     S(i,j)=1   xi=yj

                    S(i,j)=2   xi!=yj,L(i,j-1)>=L(i-1,j)

                    S(i,j)=3   xi!=yj,  L(i,j-1)<L(i-1,j)

若S(i,j)=1,则下一个搜索方向是S(i-1,j-1)

若S(i,j)=2,则下一个搜索方向是S(i,j-1)

若S(i,j)=3则下一个搜索方向是S(i-1,j)

 算法:

       输入:两个序列x和y

      输出:最长公共子序列及其长度

         1.循环变量i从0到l1重复下列操作

              L[i][0]=S[i][0]=0;

          2.循环变量i从0到l2重复下列操作

              L[0][i]=S[0][i]=0;

          3.循环变量i从1到l1重复下列操作

             3.1循环变量j从1到l2

                   3.1.1如果x[i]==y[j]

                           S[i][j]=1; L[i][j]=L[i-1][j-1]+1

                   3.1.2否则如果 L[i][j-1]>=L[i-1][j]

                          S[i][j]=2; L[i][j]=L[i][j-1]

                    3.1.3否则 S[i][j]=3;L[i][j]=L[i-1][j]

               4.使i=l1,j=l2,k=0;直到i<0 或者j<0,用字符数组path记录最长公共子序列

                  4.1如果S[i][j]==1 path[k++]=x[i],i--,j--;

                  4.2否则,如果S[i][j]=2 j--;

                   4.3否则 i--;

void dp_com(char x[], char y[],int l1,int l2) {
    int L[100][100];
    int S[100][100];
    char path[100];
    for (int i = 0; i <=l1; i++)
        L[i][0] = S[i][0] = 0;
    for (int i = 0; i <=l2; i++)
        L[0][i] = S[0][i] = 0;
    for (int i = 1; i <=l1; i++) {
        for (int j = 1; j <=l2; j++) {
            if (x[i] == y[j]) {
                S[i][j] = 1;
                L[i][j] = L[i - 1][j - 1] + 1;
            }
            else if (L[i][j-1] >=L[i-1][j]) {
                S[i][j] = 2;
                L[i][j] = L[i][j-1];
            }
            else {
                S[i][j] = 3;
                L[i][j] = L[i-1][j];
            }
        }
    }
    cout << L[l1][l2] << endl;
    int i = l1, j = l2;
    int k = 0;
    while (i >0 && j >0) {
        if (S[i][j] == 1) {
            path[k++] = x[i];
            i--;
            j--;
        }
        else if (S[i][j] == 2) j--;
        else i--;
    }
    for (i = k-1; i >= 0; i--)
        cout << path[i];
    cout << endl;
}

 

       

转载于:https://www.cnblogs.com/zuoyou151/p/9029400.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
公共序列问题(Longest Common Subsequence,简称LCS)是指在两个序列中找到一个最的公共序列,其中一个序列的所有元素按原序列中出现的顺序排列,而另一个序列中的元素则不要求按原序列中出现的顺序排列。 动态规划方法可以很好地解决LCS问题。设A和B是两个序列,LCS(A,B)表示A和B的最公共序列。则可以设计如下的状态转移方程: 当A和B的末尾元素相同时,LCS(A,B) = LCS(A-1,B-1) + 1。 当A和B的末尾元素不同时,LCS(A,B) = max(LCS(A-1,B), LCS(A,B-1))。 其中,LCS(A-1,B-1)表示A和B的末尾元素相同时的情况,LCS(A-1,B)表示A的最后一个元素不在最公共序列中,而B中的最后一个元素在最公共序列中的情况,LCS(A,B-1)表示B的最后一个元素不在最公共序列中,而A中的最后一个元素在最公共序列中的情况。 根据这个状态转移方程,可以使用动态规划算法来求解LCS问题。具体方法是,构建一个二维数组dp,其中dp[i][j]表示A前i个元素和B前j个元素的LCS。初始化dp[0][j]和dp[i][0]为0,然后按照上述状态转移方程进行递推,最终得到dp[lenA][lenB],其中lenA和lenB分别表示A和B的度。dp[lenA][lenB]即为A和B的最公共序列度。要找到具体的最公共序列,可以从dp[lenA][lenB]开始,按照状态转移方程反向推导出每个元素,即可得到最公共序列。 LCS问题动态规划算法的经典应用之一,时间复杂度为O(n*m),其中n和m分别为A和B的度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值