算法系列——动态规划8

​​​​​​718. 最长重复子数组
 

class Solution {

public:

    int findLength(vector<int>& nums1vector<int>& nums2) {

        /*dp[i][j]以数字nums1[i-1]结尾的数组与以nums2[j-1]结尾的数组的最长连续公共子数组的长度

        为什么不是以nums[i]和nums[j]结尾的呢,我想应该也是可以的,只是状态不太容易想到,

        但是做这种二维数组的子序列子数组什么的,经验之谈一般设置数组长度都会+1,这样状态转移比较容易

            ""  1   2   3   2   1

        ""  0   0   0   0   0   0

        3   0   0   0   1  (0)  0

        2   0   0   1   0   2   0

        1   0   1   0  (0)  0   3

        4   0   0   0   0   0   0

        7   0   0   0   0   0   0

        

        dp[3][3]=1  nums[i]与nums[j]相等就一定是连续的公共子数组了,至少有一个

        dp[1][4]=0  nums1[1]与nums2[4]不等 就一定不是连续的公共子数组

        所以递推公式:dp[i][j]=dp[i-1][j-1]+1,由递推公式可知遍历应该是从dp[1][1]开始遍历的,

        所以应该初始化第一行和第一列,并且是没有意义的,因为没有nums[-1]

        题目要求是要求最大值,那就取二维数组的最大值就行了

        */

        int m=nums1.size();

        int n=nums2.size();

        vector<vector<int>>dp(m+1,vector<int>(n+1));

        int res=0;

        for(int i=1;i<m+1;i++){

            for(int j=1;j<n+1;j++){

                if(nums1[i-1]==nums2[j-1]) dp[i][j]=dp[i-1][j-1]+1;

                res=max(res,dp[i][j]);

            }            

        }

        return res;

    }

};

class Solution {

public:

    int longestCommonSubsequence(string text1string text2) {

        /*dp[i][j]:以字符text[i-1]结尾的字符串与以字符text[j-1]结尾的字符串的最长公共子序列的长度

            ‘’  a   b   c   d   e

        ‘’  0   0   0   0   0   0

        a   0   1   1   1   1   1

        c   0   1   1  (2)  2   2

        e   0   1   1  (2)  2   3

        最后一个字符相同:以上dp[2][3]=2,即字符串ac与字符串abc的最长公共子序列的长度,

        他是怎么来的呢,将他们都去掉最后一个字符,

        也就是之前的dp[i-1][j-1]就是字符串ab与字符串a的最长公共子序列已经算出再加上这个公共的字符

        所以dp[i][j]=dp[i-1][j-1]+1;

        最后一个字符不同:以上dp[3][3]=2,即字符串abc与字符串ace的最长公共子序列的长度,分三种情况

        1:这两个字符都不在lcs中:dp[i][j]=dp[i-1][j-1];

        2:字符text[i]在,text[j]不在:dp[i][j]=dp[i][j-1];

        3:字符text[j]在,text[i]不在:dp[i][j]=dp[i-1][j];

        因为要求的是最长公共子序列 在之中取最大值即:

        dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]));

        

        这里可以优化一下:因为两个字符都不在lsc中的长度一定是小于其中一个在的lsc中的长度

        就可以去掉即dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

        */

        int m=text1.size();

        int n=text2.size();

        vector<vector<int>>dp(m+1,vector<int>(n+1));

        for(int i=1;i<m+1;i++){

            for(int j=1;j<n+1;j++){

                if(text1[i-1]==text2[j-1]) dp[i][j]=dp[i-1][j-1]+1;

                else dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]));

            }

        }

        return dp[m][n];

    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值