最长公共子串(动态规划)
2020-04-05 12:14
77 查看
最长公共子串(动态规划)
题目描述
给出两个数组或字符串,求其最长公共子串
给定串中任意个连续的字符组成的子序列称为该串的子串。
这是一个动态规划的题目。对于可用动态规划求解的问题,一般有两个特征:①最优子结构;②重叠子问题
先要明确怎么获取子问题。给定m,n长度的数组,其子问题是一步步把数组长度缩小找其最长公共子串。从最小各自长度为1,套用双层循环一层层增加两个数组长度。
设A=“a0,a1,…,am”,B=“b0,b1,…,bn”,且Z=“z0,z1,…,zk”为它们的最长公共子序列。不难证明有以下性质:
如果am=bn,则zk=am=bn,且“z0,z1,…,z(k-1)”是“a0,a1,…,a(m-1)”和“b0,b1,…,b(n-1)”的一个最长公共子序列;
如果am!=bn,则若zk!=am,蕴涵“z0,z1,…,zk”是“a0,a1,…,a(m-1)”和“b0,b1,…,bn”的一个最长公共子序列;
如果am!=bn,则若zk!=bn,蕴涵“z0,z1,…,zk”是“a0,a1,…,am”和“b0,b1,…,b(n-1)”的一个最长公共子序列。
动态转移方程:
按照这个套用循环即可填充下图:
这个对应A数组1个长度,循环B数组从1到n;然后填充整个图:
#include<bits/stdc++.h> using namespace std; int m,n,dp[100][100],t[100][100],a[100],b[100]; void print(int i,int j) { if(i==0||j==0) return; if(t[i][j]==1) { print(i-1,j-1); cout<<a[i]; } else if(t[i][j]==2) { print(i-1,j); } else print(i,j-1); } int main() { int m,n; cin>>m>>n; for(int i=1;i<=m;i++) cin>>a[i]; for(int i=1;i<=n;i++) cin>>b[i]; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { if(a[i]==b[j]) { dp[i][j]=dp[i-1][j-1]+1; t[i][j]=1; //左上 } else { if(dp[i-1][j]>dp[i][j-1]) { dp[i][j]=dp[i-1][j]; t[i][j]=2; //左 } else { dp[i][j]=dp[i][j-1]; t[i][j]=3; //右 } } } } for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { cout<<t[i][j]<<" "; } cout<<endl; } print(m,n); }
打印出来 T[][]方便理解
每次打印,只有a[i]==b[j]表示公共字符才打印,否则返回上一级继续寻找
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 算法题39 最长公共子串--动态规划
- 动态规划求解最长公共子序列与最长公共子串
- 0012算法笔记——【动态规划】最长公共子串问题
- 递归与动态规划---最长公共子串问题
- 最长公共子串(动态规划)
- 最大子序列、最长连续公共子串(连续)、最长公共子序列(动态规划)
- 动态规划 - 最长公共子序列 - 最长公共子串 - 最长不重复子串 - 最长递增子序列 - 最长回文子串
- 动态规划解决最长公共子序列和最长公共子串
- 最长公共子串(动态规划)
- 动态规划(6)最长公共子串
- 动态规划 最长公共子串问题 记录一下
- 利用后缀数组求字符串的最长重复子串的算法 利用二维数组求两个字符串的最长公共字串(动态规划)
- 动态规划-最长公共子串问题-java版
- 最长公共子串问题 动态规划
- 动态规划求解最长公共子串中的问题
- 求两个字符串最长公共子串(动态规划)
- 【动态规划】最长公共子串问题
- 最长公共子串【动态规划解法】
- [动态规划]最长公共子串长度问题
- leetcode 718. Maximum Length of Repeated Subarray 最长公共子串 + 动态规划DP