原题链接Maximum Length of Repeated Subarray

计算两个序列最长的相同子序列的长度


简单暴力的方法是对A中每个元素遍历一遍序列B,找到相同的位置后计算从这个位置开始有多少个元素和A是相同的,唔…大概是这个样子

class Solution {
public:int findLength(vector<int>& A, vector<int>& B) {int maxLen = 0;for(int i = 0; i < A.size(); ++i){for(int j = 0; j < B.size(); ++j){if(A[i] != B[j])continue;int len = 0;int p = i, q = j;while(p != A.size() && q != B.size() && A[p] == B[q]){++p;++q;++len;}maxLen = std::max(maxLen, len);}}return maxLen;}
};

不过超时了:(,想想也觉得没这么容易


假设序列A的长度为m,序列B的长度为n。

考虑两个序列的相同子序列

A[i, i+1, ..., i+k]
B[j, j+1, ..., j+k]

将这两个子序列分别延伸到序列末尾

A[i, i+1, ..., m-1]
B[j, j+1, ..., n-1]

那么,可以把公共子序列看成是序列A[i : m-1]和B[j : n-1]的最长公共前缀

转换成动态规划,设dp[i][j]表示A[i : m-1]和B[j : n-1]的最长公共前缀,那么

if(A[i] == B[j])dp[i][j] = 1 + dp[i + 1][j + 1];
elsedp[i][j] = 0;

如果A[i] == B[j],那么A[i : m-1]和B[j : n-1]的第一个位置已经相等,只需计算A[i+1 : m-1]和B[j+1 : n-1]的最长公共前缀

如果A[i] != B[j],那么A[i : m-1]和B[j : n-1]第一个位置就不相等,显然没有公共前缀

代码如下

class Solution {
public:int findLength(vector<int>& A, vector<int>& B) {vector<vector<int>> dp(A.size()+1, vector<int>(B.size()+1, 0));int maxLen = 0;for(int i = A.size() - 1; i >= 0; --i){for(int j = B.size() - 1; j >= 0; --j){if(A[i] == B[j]){/* 更新dp[i][j] */dp[i][j] = 1 + dp[i + 1][j + 1];maxLen = std::max(maxLen, dp[i][j]);}}}return maxLen;}
};

当然了,既然是迭代法实现的动态规划,那么就能将动态规划数组降维

观察二维动态规划数组的更新情况,整个程序只用到了dp[i][j]和dp[i+1][j+1],又因为i在外层循环,所以可以改为dp[j] = dp[j+1],不过需要改变内层循环的遍历顺序

class Solution {
public:int findLength(vector<int>& A, vector<int>& B) {vector<int> dp(B.size() + 1, 0);int maxLen = 0;for(int i = A.size() - 1; i >= 0; --i){/* 遍历顺序颠倒 */for(int j = 0; j < B.size(); ++j){/* 相等和不相等两种情况 */dp[j] = (A[i] == B[j]) ? 1 + dp[j + 1] : 0;maxLen = std::max(maxLen, dp[j]);}}return maxLen;}
};

为了便于理解,可以

  • 把dp[j]看成dp[i][j],表示当前的i当前的j

  • 把dp[j+1]看成dp[i+1][j+1],表示上次循环的i和下次循环的j

假设有I1, J1, J11表示某次循环时的i,j和j+1,下一轮外层循环时i,j和j+1改为I2,J1,J11。

以下称为第一次和第二次循环

在第二次循环过程中,假设正要执行但还没有执行

dp[j] = (A[i] == B[j]) ? 1 + dp[j + 1] : 0;

写成上面符号的格式是

dp[J1] = (A[I2] == B[J1]) ? 1 + dp[J11] : 0;

因为j是从0到B.size()的,所以只有更新完dp[J1]后才会更新dp[J11],当准备更新dp[J1]时,dp[J11]还没有被更新

没有被更新的意思是dp[J11]的值在上次更新后没有被改变,上次更新时的i是I1,j是J11,所以dp[J11] == dp[I1][J11]

因为i是从A.size()到0的,所以I1 = I2 + 1,所以

dp[J11] == dp[I1][J11] == dp[I2 + 1][J11]

对于正要更新的dp[J1],此时的i是I2,所以

dp[J1] == dp[I2][J1]

所以上面的更新过程可以改为

dp[I2][J1] = (A[I2] == B[J1]) ? 1 + dp[I2 + 1][J11] : 0;

由于J11 == J1 + 1,所以

dp[I2][J1] = (A[I2] == B[J1]) ? 1 + dp[I2 + 1][J1 + 1] : 0;

形式和

dp[i][j] = (A[i] == B[j]) ? 1 + dp[i + 1][j + 1] : 0;

相同

每天一道LeetCode-----计算两个序列最长的公共子序列长度相关推荐

  1. 两个字符串的最长公共子序列长度_算法学习笔记(58): 最长公共子序列

    (为什么都更了这么多篇笔记了,这时候才讲这么基础的内容呢?因为我本来以为LCS这种简单的DP不用讲的,结果CF不久前考了LCS的变式,然后我发现由于自己对LCS一点都不熟,居然写不出来 ,于是决定还是 ...

  2. 两个字符串的最长公共子序列长度_求2个字符串的最长公共子序列和最长公共子字符串...

    一. 最长公共子序列 定义: 一个数列S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列. 例如:输入两个字符串BDCABA和 ABCBDA ...

  3. 两个字符串的最长公共子序列长度_【面试】动态规划-之最长公共子序列、最长公共子串问题...

    先来说明下什么是最长公共子序列,什么是是最长公共子串,举一个实际例子,myblogs与belong,最长公共子序列为blog(myblogs, belong),最长公共子串为lo(myblogs, b ...

  4. 【leetcode】【动态规划】最长回文子序列

    [leetcode]最长回文子序列 题目 代码 leetcode题目地址 题目 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度. 子序列定义为:不改变剩余字符顺序的情况下,删除某些 ...

  5. 两个字符串的最长公共子序列长度_程序员编程算法,解决文本相似度问题的最长公共子序列算法!...

    在前面我讲解了如何通过最长公共子串来求解两个文本的相似度问题,但它有一定缺陷,举个例子,看下面的两个字符串 我爱吃小青菜和各种鲜水果. 我很爱吃青菜与各样水果. 上面两个字符串,如果通过计算子串来求相 ...

  6. 求序列最长不下降子序列_最长不下降子序列nlogn算法详解

    今天花了很长时间终于弄懂了这个算法--毕竟找一个好的讲解真的太难了,所以励志我要自己写一个好的讲解QAQ 这篇文章是在懂了这个问题n^2解决方案的基础上学习. 解决的问题:给定一个序列,求最长不下降子 ...

  7. 求序列最长不下降子序列_树状数组解决最长不下降子序列 讲讲主要思路就好...

    展开全部 不降子序列求的是一个元素的值单调e69da5e887aa62616964757a686964616f31333361306430不降的序列. 传统的状态设计便是使用f[n] 表示到达第n位时 ...

  8. 两个字符串的最长公共子序列长度_输出两个字符串的最长公共子串和最长公共子序列...

    输出两个字符串的最长公共子串和最长公共子序列.求解两个字符串的最长公共子串和最长公共子序列在方法上很接近,都是动态规划.只不过在递推方程上有一些不一样. 求两个字符串的最长公共子串 #include ...

  9. LeetCode 1458. 两个子序列的最大点积(动态规划,类似编辑距离)

    1. 题目 给你两个数组 nums1 和 nums2 . 请你返回 nums1 和 nums2 中两个长度相同的 非空 子序列的最大点积. 数组的非空子序列是通过删除原数组中某些元素(可能一个也不删除 ...

最新文章

  1. x+2y+3z=n的非负整数解数
  2. Ice笔记--C++线程与并发(小结)
  3. 读入一段文本到 vector 对象,每个单词存储为 vector 中的一个元素。把 vector 对象中每个单词转化为大写字母。输出 vector 对象中转化后的元素,每八个单词为一行输出。
  4. Arturia Prophet V3 for Mac(多功能仿真音乐合成器)
  5. 百亿级别数据量,又需要秒级响应的案例,需要什么系统支持呢?下面介绍下大数据实时分析工具Yonghong Z-Suite...
  6. 白盒测试实践作业进度报告——Day 3
  7. RPM的原理及rpm命令常用参数
  8. squid服务的应用 转
  9. 电容(2)——电容在电路中的作用
  10. php图片幻灯片代码,解决phpcms更换javascript的幻灯片代码调用图片问题
  11. 论文:OIE@OIA: an Adaptable and Efficient Open Information Extraction Framework
  12. 什么是Python中的套接字编程?
  13. 那个学php的上吊了,这位一路名校的中国博士,突然在美国上吊自杀了
  14. R语言学习笔记(二) 逻辑运算符
  15. el-tree中更改鼠标移动时、点击时和失去焦点时的背景色
  16. 【滑窗】B024_LC_和相同的二元子数组(暴力前缀和 / map 优化)
  17. 自动载入实战---构造一个PSR-0的简易框架
  18. PHP获取IP地址的五种方法
  19. 概率论与数理统计期末复习题(1)
  20. 诺基亚(NOKIA)手机 功能代码

热门文章

  1. 刷圈兔下载_刷圈兔app
  2. C语言学习用迭代法求x=√a
  3. 云笔记项目-过滤器与拦截器学习
  4. websocket实现单聊
  5. AngularJS:SQL
  6. git diff命令详解
  7. java--杨辉三角
  8. NYOJ--517--最小公倍数(大数打表)
  9. 调用支付宝PHP接口API实现在线即时支付功能(UTF-8编码)
  10. Day11多态部分-6 【1.4 多态的应用以及注意事项】