lintcode longest-common-subsequence 最长公共子序列 证明

问题描述

lintcode

参考

coursera-北京大学-算法基础-动态规划(1)-几个例题

笔记

动态规划问题,同样要建表。
buff[i][j]表示以字符串A的第i位结束,以字符串B的第j位结束,的最长公共子序列。
状态转移方程:

if (A[i] == B[j])   
    buff[i][j] = buff[i-1][j-1] + 1;
else
    buff[i][j] = max(buff[i-1][j], buff[i][j-1]);

解释:

规定:

  1. S[i][j]的含义是<以A的第i位结尾的字符串>与<以B的第j位结尾的字符串>的最长公共子序列。S[i-1][j-1]的含义是<以A的第i-1为结尾的字符串>与<以B的第j-1位结尾的字符串>的最长公共子序列。

  2. buff[i][j]为S[i][j]的长度。

  • A[i] == B[j]
    显然,由于两个字符串的最后一位相同,S[i][j]的长度应该比S[i-1][j-1]大1.

  • A[i] != B[j]
    结论是:buff[i][j] = max(buff[i-1][j], buff[i][j-1])

    • 证明:

      1. 显然,由于添加了一个字符,buff[i][j] 肯定大于等于buff[i-1][j],也肯定大于等于buff[i][j-1]
      2. 但是,buff[i][j] 不能同时大于 buff[i-1][j]buff[i][j-1]
        反证法:
        1.1. 如果buff[i][j] > buff[i-1][j],说明S[i][j]的最后一位是A[i]。(因为多了A[i]这个字符之后,最长公共子序列的长度多了1,所以多出来的这一位就是A[i]!)
        1.2. 同理,如果buff[i][j] > buff[i][j-1],说明S[i][j]的最后一位是B[j]
        1.3. 那么如果buff[i][j] 同时大于 buff[i-1][j]buff[i][j-1],说明S[i][j]的最后一位既是A[i],也是B[j]。那么A[i]就与B[j]相同了!矛盾了!所以反证出:
        buff[i][j] 不能同时大于 buff[i-1][j]buff[i][j-1]

      3. 现在,已经证明了,buff[i][j] 肯定大于等于buff[i-1][j],也肯定大于等于buff[i][j-1],(图中绿色区域)但buff[i][j] 不能同时大于 buff[i-1][j]buff[i][j-1],那buff[i][j]就只能取两者的较大者了(图中红星),这样既满足”不能同时大于两者“(只大于较小者),又满足”同时大于等于两者“,(大于较小者, 等于较大者)。
        这里写图片描述

代码

class Solution {
public:
    /**
     * @param A, B: Two strings.
     * @return: The length of longest common subsequence of A and B.
     */
    int longestCommonSubsequence(string A, string B) {
        // write your code here
        const int lena = A.size();
        const int lenb = B.size();
        int buff[lena+1][lenb+1];
        memset(buff, 0, sizeof(buff));
        for (int i = 1; i <= lena; i++)
        {
            for (int j = 1; j <= lenb; j++)
            {
                if (A[i-1] == B[j-1])
                    buff[i][j] = buff[i-1][j-1] + 1;
                else
                    buff[i][j] = max(buff[i-1][j], buff[i][j-1]);
            }
        }
        return buff[lena][lenb];
    }
};


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值