动态规划解最长公共子序列问题
- 格式:doc
- 大小:77.50 KB
- 文档页数:9
公共子序列问题徐康123183一.算法设计假设有两个序列X和Y,假设X和Y分别有m和n个元素,则建立一个二维数组C[(m+1)*(n+1)],记录X i与Y j的LCS的长度。
将C[i,j]分为三种情况:若i =0 或j =0时,C[i,j]=0;若i,j>0且X[i]=Y[j],C[i,j]=C[i-1,j-1]+1;若i,j>0且X[i] Y[j],C[i,j]=max{C[i-1,j],C[i,j-1]}。
再使用一个m*n的二维数组b,b[i,j]记录C[i,j]的来向:若X[i]=Y[j],则B[i,j]中记入“↖”,记此时b[i,j] = 1;若X[i] Y[j]且C[i-1,j] > C[i,j-1],则b[i,j]中记入“↑”,记此时B[i,j] = 2;若X[i] Y[j]且C[i-1,j] < C[i,j-1],则b[i,j]中记入“←”,记此时B[i,j] = 3;若X[i]Y[j]且C[i-1,j] = C[i,j-1],则b[i,j]中记入“↑”或“←”,记此时B[i,j] = 4;得到了两个数组C[]和B[],设计递归输出LCS(X,Y)的算法:LCS_Output(Direction[][], X[], i, j, len,LCS[]){If i=0 or j=0 将LCS[]保存至集合LCS_SET中then return;If b[i,j]=1 then /*X[i]=Y[j]*/{LCS_Output(b,X,i-1,j-1);将X[i]保存至LCS[len-i];}else if b[i,j]=2 then /*X[i]Y[j]且C[i-1,j]>C[i,j-1]*/LCS_Output(b,X,i-1,j)else if b[i,j]=3 then /*X[i]Y[j]且C[i-1,j]<C[i,j-1]*/ LCS_Output(b,X,i,j-1)else if b[i,j]=4 then /*X[i]Y[j]且C[i-1,j]=C[i,j-1]*/LCS_Output(b,X,i-1,j)LCS_Output(b,X,i,j-1)}二.算法时间复杂度分析由上述对算法的分析得知,求辅助数组C 和B 所消耗的时间复杂度为O (mn ),而查找所有的公共子序列的时间复杂度取决于所遍历的路径,而路径是由算法递归的方向决定的。
最长公共子序列(Longest Common Subsequence, LCS)是指在两个序列中找到的最长公共非连续子序列。
求解两个序列的最长公共子序列的递推次序是一道经典的动态规划问题,本文将针对这一主题展开详细的描述和分析。
一、问题描述给定两个序列X={x1, x2, ..., xm}和Y={y1, y2, ..., yn},要求找出它们的最长公共子序列。
对于序列X={A, B, C, B, D, A, B}和Y={B, D, C, A, B, A},它们的最长公共子序列是{B, C, A, B},长度为4。
二、递推关系在动态规划的思想下,我们可以通过构造一个二维数组来解决这个问题。
假设L[i][j]表示序列X的前i个元素和序列Y的前j个元素的最长公共子序列的长度,那么L[i][j]的递推关系可以表示为:1. 当i=0或j=0时,L[i][j]=0;2. 当xi=yj时,L[i][j]=L[i-1][j-1]+1;3. 当xi≠yj时,L[i][j]=max{L[i-1][j], L[i][j-1]}。
三、动态规划的实现在实际编程中,我们可以使用一个二维数组来存储L[i][j]的值。
我们需要初始化L[0][j]和L[i][0]为0;根据上述递推关系,使用一个双重循环来填充数组L,最终得到L[m][n]的值,即序列X和Y的最长公共子序列的长度。
四、回溯求解最长公共子序列在获得了二维数组L之后,我们可以通过回溯的方法来求解最长公共子序列的具体内容。
从L[m][n]开始,我们可以根据递推关系,逆向推导出最长公共子序列的元素,直到回溯到L[0][0]为止。
这样就可以得到最长公共子序列的具体内容。
五、优化在实际应用中,为了提高动态规划的效率,可以对上述算法进行优化。
例如使用滚动数组来降低空间复杂度,或者采用其他策略来减少不必要的计算。
六、总结本文针对求解两个序列的最长公共子序列的递推次序进行了详细的分析和描述。
利用递归求最长公共子序列问题1.引言最长公共子序列(Longest Common Subsequence,简称LCS)是一个经典的动态规划问题,其可以描述为:给定两个序列X和Y,求出它们的最长公共子序列的长度。
在计算机科学领域,LCS问题广泛应用于字符串比较、文本相似度计算、基因序列比对等领域,因此对于LCS问题的求解具有重要的意义。
2.问题描述对于序列X和Y,它们的最长公共子序列可以定义为:如果一个序列Z既是X的子序列又是Y的子序列,且Z的长度最大,那么Z称为X和Y的最长公共子序列。
3.递归解法我们可以使用递归的方式来解决LCS问题。
递归的思想是将原问题划分为更小的子问题求解,然后将子问题的解合并起来得到原问题的解。
对于LCS问题,我们可以将其划分为更小的子问题求解。
假设X和Y的长度分别为m和n,我们可以考虑X中的第m个元素和Y中的第n 个元素是否相等,从而将原问题划分为以下三种情况:a) 如果X[m]等于Y[n],那么X和Y的最长公共子序列就是X[1..m-1]和Y[1..n-1]的最长公共子序列再加上X[m]。
b) 如果X[m]不等于Y[n],那么X和Y的最长公共子序列就是X[1..m-1]和Y[1..n]的最长公共子序列,或者是X[1..m]和Y[1..n-1]的最长公共子序列,取两者的最大值。
c) 如果X或Y的长度为0,那么它们的最长公共子序列的长度为0。
4.递归求解步骤基于上述的划分情况,我们可以得到递归求解LCS问题的步骤如下:a) 如果X和Y的最后一个元素相等,那么LCS(X, Y, m, n) = 1 + LCS(X, Y, m-1, n-1);b) 如果X和Y的最后一个元素不相等,那么LCS(X, Y, m, n) = max(LCS(X, Y, m-1, n), LCS(X, Y, m, n-1));c) 如果m等于0或n等于0,那么LCS(X, Y, m, n) = 0。
问题描述:一个给定序列的子序列是在该序列中删去若干元素后得到的序列。
确切地说,若给定序列X= { x1, x2,…, x m},则另一序列Z= {z1, z2,…, z k}是X的子序列是指存在一个严格递增的下标序列{i1, i2,…, i k},使得对于所有j=1,2,…,k有X ij=Z j。
例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
例如,若X= { A, B, C, B, D, A, B}和Y= {B, D, C, A, B, A},则序列{B,C,A}是X和Y的一个公共子序列,序列{B,C,B,A}也是X和Y的一个公共子序列。
而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。
给定两个序列X= {x1, x2, …, x m}和Y= {y1, y2, … , y n},要求找出X和Y的一个最长公共子序列。
问题解析:设X= { A, B, C, B, D, A, B},Y= {B, D, C, A, B, A}。
求X,Y的最长公共子序列最容易想到的方法是穷举法。
对X的多有子序列,检查它是否也是Y的子序列,从而确定它是否为X和Y的公共子序列。
由集合的性质知,元素为m的集合共有2^m个不同子序列,因此,穷举法需要指数级别的运算时间。
进一步分解问题特性,最长公共子序列问题实际上具有最优子结构性质。
设序列X={x1,x2,……x m}和Y={y1,y2,……y n}的最长公共子序列为Z={z1,z2,……z k}。
则有:(1)若x m=y n,则z k=x m=y n,且z k-1是X m-1和Y n-1的最长公共子序列。
(2)若x m!=y n且z k!=x m,则Z是X m-1和Y的最长公共子序列。
用动态规划法解决最长公共子序列问题动态规划解最长子序列一、课程设计目的掌握动态规划法的原理,并能够按其原理编程实现求两个序列数据的最长公共子系列,以加深对其的理解。
二、课程设计内容1、用动态规划法解决最长子序列问题2、交互输入两个序列数据3、输出两个序列的最长公共子序列三、概要设计四、详细设计与实现#include "iostream.h"#include "iomanip.h"#define max 100void LCSLength(int m,int n,char *x,char *y,char *b){int i,j,k;int c[max][max];for(i=1;i<=m;i++){c[i][0]=0;}for(i=1;i<=n;i++){c[0][i]=0;}for(i=1;i<=m;i++){for(j=1;j<=n;j++){if(x[i-1]==y[j-1]){c[i][j]=c[i-1][j-1]+1;k=i*(n+1)+j;b[k]='\\';}else if(c[i-1][j]>=c[i][j-1]){c[i][j]=c[i-1][j];k=i*(n+1)+j;b[k]='|';}else{c[i][j]=c[i][j-1];k=i*(n+1)+j;b[k]='-';}}}}void LCS(int i,int j,char *x,char *b,int width) {if(i==0 || j==0)return;int k=i*(width+1)+j;if(b[k]=='\\'){LCS(i-1,j-1,x,b,width);cout<<x[i]<<endl;}else if(b[k]=='|'){LCS(i-1,j,x,b,width);}else{LCS(i,j-1,x,b,width);}}void main(){char x[max]={'a','b','c','b','d','a','b'};char y[max]={'b','d','c','a','b','a'};int m=7;int n=6;char b[max]={0};LCSLength(m,n,x,y,b);LCS(m,n,x,b,n);cout<<endl<<endl;}最长公共子序列问题具有最优子结构性质设X = { x1 , ... , xm }Y = { y1 , ... , yn }及它们的最长子序列Z = { z1 , ... , zk }则1、若 xm = yn ,则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列2、若 xm != yn ,且 zk != xm , 则 Z 是 X[m-1] 和 Y 的最长公共子序列3、若 xm != yn , 且 zk != yn , 则 Z 是 Y[n-1] 和 X 的最长公共子序列由性质导出子问题的递归结构当 i = 0 , j = 0 时 , c[i][j] = 0当 i , j > 0 ; xi = yi 时 , c[i][j] = c[i-1][j-1] + 1当 i , j > 0 ; xi != yi 时 , c[i][j] = max { c[i][j-1] , c [i-1][j] }#include<iostream.h>#define max(a,b) a>b?a:b#define M 100void display(int &n,int &C,int w[M],int v[M]) {int i;cout<<"请输入物品种数n:";cin>>n;cout<<endl;cout<<"请输入背包总容量C:";cin>>C;cout<<endl;cout<<"请输入各物品的大小或重量w:"<<endl;w[0]=0;for(i=1;i<=n;i++)cin>>w[i];cout<<"请输入各物品其价值v:"<<endl;v[0]=0;for(i=1;i<=n;i++)cin>>v[i];};int knapsack(int &n,int &C,int w[M],int v[M],int V[M][M]){int i,j;for (i=0;i<=n;i++)for(j=0;j<=C;j++){if(i==0||j==0)V[i][j]=0;else if(w[i]>j)V[i][j]=V[i-1][j];else if(w[i]<=j)V[i][j]=max(V[i-1][j],V[i-1][j-w[i]]+v[i]);}return V[n][C];};void traceback(int n,int C,int w[M],int x[M],int V[M][M]){for(int i=1;i<=n;i++){if(V[i][C]==V[i-1][C])x[i]=0;else{x[i]=1;C=C-w[i];}}//x[n]=(V[n][C]>0)?1:0;};void main(){int i,j,n,C;char ch;int w[M],v[M],x[M];int V[M][M];while(1){display(n,C,w,v);cout<<"运算结果如下:"<<endl;for(i=1;i<=n;i++)x[i]=0;knapsack(n,C,w,v,V);cout<<" ";for(j=0;j<=C;j++)cout<<j<<" ";cout<<endl;for(i=0;i<=n;i++){cout<<i<<" ";for(j=0;j<=C;j++){cout<<V[i][j]<<" ";}cout<<endl;cout<<endl;}cout<<"选择的物向量表示为:";cout<<" ( ";traceback(n,C,w,x,V);for(i=1;i<=n;i++)cout<<x[i]<<" ";cout<<")"<<endl;cout<<"背包最大价值为:"<<V[n][C]<<endl;cout<<endl;cout<<"按Y或y继续操作,否则按任意键"<<endl;cin>>ch;if(ch=='Y'||ch=='y')continue;elsebreak;} }。
最长公共子序列问题;最长公共子序列(Longest Common Subsequence, LCS)问题是指找到多个字符串中最长的公共子序列。
公共子序列是指这些字符串在所有字符串中都以相同的顺序出现,但不要求连续。
例如,对于字符串"ABCD"和"ACDF",其最长公共子序列为"ACD"。
最长公共子序列问题可以通过动态规划来解决。
基本思路是使用一个二维数组dp,其中dp[i][j]表示字符串A的前i个字符和字符串B的前j个字符的最长公共子序列的长度。
首先,初始化dp[0][j]和dp[i][0]为0,表示空字符串与任何字符串的最长公共子序列长度为0。
然后,对于每个字符A[i]和B[j],如果A[i]等于B[j],则dp[i][j] = dp[i-1][j-1] + 1,表示在之前的最长公共子序列长度的基础上加1。
否则,dp[i][j] = max(dp[i-1][j], dp[i][j-1]),表示要么在字符串A的前i-1个字符和字符串B的前j个字符的最长公共子序列的基础上取得,要么在字符串A的前i个字符和字符串B的前j-1个字符的最长公共子序列的基础上取得。
最终,dp[m][n]即为所求,其中m和n分别为字符串A和字符串B的长度。
可以通过追踪dp数组来还原出最长公共子序列,具体方法是从dp[m][n]开始,如果A[i]等于B[j],则该字符是公共字符,将其加入结果序列,然后向左上方移动,即dp[i-1][j-1]。
如果dp[i][j]等于dp[i-1][j],则说明最长公共子序列在A中取得,向上移动,即dp[i-1][j];如果dp[i][j]等于dp[i][j-1],则说明最长公共子序列在B中取得,向左移动,即dp[i][j-1]。
重复上述过程,直到dp[i][j]为0。
公共解的三种解法
#### 1. 动态规划
使用动态规划的方法,可以把求解最大公共子序列问题转换为求解最长公共子序列问题。
动态规划的思路是:令dp[i][j]表示字符串A[0..i]和字符串B[0..j]的最长公共子序列的长度,则有状态转移方程:
```
dp[i][j] =
0 (i == 0 || j == 0)
dp[i-1][j-1] + 1 (A[i] == B[j])
max(dp[i-1][j], dp[i][j-1]) (A[i] != B[j])
```
最终结果为dp[n][m],其中n为字符串A的长度,m为字符串B的长度。
#### 2. 递归
递归的思路是:令lcs(i, j)表示字符串A[0..i]和字符串B[0..j]的最长公共子序列的长度,则
有状态转移方程:
```
lcs(i, j) =
0 (i == 0 || j == 0)
lcs(i-1, j-1) + 1 (A[i] == B[j])
max(lcs(i-1, j), lcs(i, j-1)) (A[i] != B[j])
```
最终结果为lcs(n, m),其中n为字符串A的长度,m为字符串B的长度。
#### 3. 滑动窗口
滑动窗口的思路是:定义两个指针i和j,分别指向字符串A和字符串B的开头,比较A[i]
和B[j]的值,如果相等,则将i和j同时向后移动,否则只有一个指针向后移动,直到两个
指针都到达字符串末尾。
最终结果为i和j指针移动的次数,即为最长公共子序列的长度。
算法设计最长公共子序列动态规划是一种将大问题分解为多个相互重叠的子问题的方法。
在LCS算法中,我们将两个字符串的比较拆分为子问题,然后通过子问题的解决来解决整个问题。
算法步骤如下:1. 初始化一个二维数组dp[m+1][n+1],其中m和n分别是两个字符串的长度,dp[i][j]表示字符串1的前i个字符和字符串2的前j个字符之间的LCS的长度。
2. 将dp的第一行和第一列初始化为0,表示空字符串和任何其他字符串之间的LCS的长度都为0。
3.使用两个循环迭代字符串1和字符串2的每个字符。
从1开始,递增地遍历每个字符的位置。
4. 比较当前字符是否相等。
如果相等,则将dp[i][j]设置为dp[i-1][j-1]+1,表示LCS的长度增加15. 如果当前字符不相等,则将dp[i][j]设为dp[i-1][j]和dp[i][j-1]中的最大值,表示LCS的长度不变。
6.继续向前迭代不同字符的位置,直到处理完所有字符。
7. 当迭代完成后,dp[m][n]的值即为字符串1和字符串2的最长公共子序列的长度。
8. 可以使用回溯法来找到LCS本身。
从dp[m][n]位置开始,根据dp[i][j]的值,在字符串1和字符串2中向左上方移动,直到dp[i][j]等于0。
这样就找到了最长公共子序列。
该算法的时间复杂度为O(m*n),其中m和n分别是两个字符串的长度。
这是因为遍历了两个字符串的所有字符,并在每个字符位置上进行了常量时间的比较和更新。
LCS算法可以应用于多个领域,包括字符串处理、DNA序列分析、版本控制系统等。
通过找到最长公共子序列,可以找到相似的字符或序列,并从中提取有用的信息。
例如,对于字符串1:"ABCBDAB"和字符串2:"BDCAB",可以使用LCS算法找到它们的最长公共子序列为:"BCAB",其长度为4。
动态规划经典——最长公共⼦序列问题(LCS)和最长公共⼦串问题⼀.最长公共⼦序列问题(LCS问题)给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共⼦序列,并返回其长度。
例如: A = "Hel lo W o rld" B = "loo p"则A与B的最长公共⼦序列为 "loo",返回的长度为3。
此处只给出动态规划的解法:定义⼦问题dp[i][j]为字符串A的第⼀个字符到第 i 个字符串和字符串B 的第⼀个字符到第 j 个字符的最长公共⼦序列,如A为“app”,B为“apple”,dp[2][3]表⽰ “ap” 和 “app” 的最长公共字串。
注意到代码中 dp 的⼤⼩为 (n + 1) x (m + 1) ,这多出来的⼀⾏和⼀列是第 0 ⾏和第 0 列,初始化为 0,表⽰空字符串和另⼀字符串的⼦串的最长公共⼦序列,例如dp[0][3]表⽰ "" 和“app” 的最长公共⼦串。
当我们要求dp[i][j],我们要先判断A的第i个元素B的第j个元素是否相同即判断A[i - 1]和 B[j -1]是否相同,如果相同它就是dp[i-1][j-1]+ 1,相当于在两个字符串都去掉⼀个字符时的最长公共⼦序列再加 1;否则最长公共⼦序列取dp[i][j - 1] 和dp[i - 1][j]中⼤者。
所以整个问题的初始状态为:dp[i][0]=0,dp[0][j]=0相应的状态转移⽅程为:dp[i][j]=max{dp[i−1][j],dp[i][j−1]},A[i−1]!=B[j−1] dp[i−1][j−1]+1,A[i−1]==B[j−1]代码的实现如下:class LCS{public:int findLCS(string A, int n, string B, int m){if(n == 0 || m == 0)//特殊输⼊return 0;int dp[n + 1][m + 1];//定义状态数组for(int i = 0 ; i <= n; i++)//初始状态dp[i][0] = 0;for(int i = 0; i <= m; i++)dp[0][i] = 0;for(int i = 1; i <= n; i++)for(int j = 1; j<= m; j++){if(A[i - 1] == B[j - 1])//判断A的第i个字符和B的第j个字符是否相同dp[i][j] = dp[i -1][j - 1] + 1;elsedp[i][j] = max(dp[i - 1][j],dp[i][j - 1]);}return dp[n][m];//最终的返回结果就是dp[n][m]}};该算法的时间复杂度为O(n*m),空间复杂度为O(n*m)。
动态规划问题常见解法
动态规划是一种高效解决优化问题的方法。
它通常用于涉及最
优化问题和最短路径的计算中。
下面是一些常见的动态规划问题解法:
1. 背包问题
背包问题是动态规划中的经典问题之一。
其目标是在给定的背
包容量下,选择一些物品放入背包中,使得物品总价值最大。
解决
这个问题的常见方法是使用动态规划的思想,定义一个二维数组来
记录每个物品放入背包时的最大价值,然后逐步计算出最终的结果。
2. 最长公共子序列问题
最长公共子序列问题是寻找两个字符串中最长的公共子序列的
问题。
解决这个问题的常见方法是使用动态规划的思想,定义一个
二维数组来记录两个字符串中每个位置的最长公共子序列的长度。
然后通过递推关系来计算出最终的结果。
3. 矩阵链乘法问题
矩阵链乘法问题是计算一系列矩阵相乘的最佳顺序的问题。
解
决这个问题的常见方法是使用动态规划的思想,定义一个二维数组
来记录每个矩阵相乘时的最小乘法次数,然后逐步计算出最终的结果。
4. 最长递增子序列问题
最长递增子序列问题是寻找一个序列中最长的递增子序列的问题。
解决这个问题的常见方法是使用动态规划的思想,定义一个一
维数组来记录每个位置处的最长递增子序列的长度,然后通过递推
关系来计算出最终的结果。
以上是一些常见的动态规划问题解法。
通过灵活运用这些方法,我们可以更高效地解决优化问题和最短路径计算等相关任务。
动态规划求解最长公共子串问题算法思想求字符串str1,str2的最长公共子串的长度。
定义二元函数函数f(m,n):分别以str1[m],str2[n]结尾的连续公共子串的长度而对于f(m+1,n+1) 有以下两种情况1.str1[m+1] != str2[n+1],则有f(m+1,n+1) =02.str1[m+1] == str2[n+1],则有f(m+1,n+1) = f(m,n) + 1另外f(0,j) = 0(j>=0)f(j,0) = 0 (j>=0)按照上面这个公式,我们用容易写出这个算法的实现算法实现1 int commstr(char *str1, char *str2)2 /* 返回str1,str2的最长公共之串长度*/3 {4 int len1=strlen(str1),len2=strlen(str2),row,col,max=0;5 int **pf = new int*[len1+1];//动态分配一个二维数组作为辅助空间6 for (row=0; row<len1+1; row++)7 pf[row] = new int[len2+1];89 //数组赋初值10 for (row=0; row<len1+1; row++)11 pf[row][0] = 0;12 for (col=0; col<len2+1; col++)13 pf[0][col] = 0;1415 for (row=1; row<=len1; row++)16 for (col=1;col<=len2; col++)17 {18 if (str1[row-1] == str2[col-1])19 {20 pf[row][col] = pf[row-1][col-1] + 1;21 max = pf[row][col] > max ? pf[row][col] : max;22 }23 else24 pf[row][col] = 0;25 }26 //空间回收27 for (row=0; row<len1+1; row++)28 delete[] pf[row];29 delete[] pf;3031 return max;32 }程序的输出字符串""和"csdn.blog"求公共子串时的输出结果String:1. 2. csdn.blogc sd n . b l o g0 0 0 0 0 0 0 0 0 0b 0 0 0 0 0 0 1 0 0 0l 0 0 0 0 0 0 0 2 0 0o 0 0 0 0 0 0 0 0 3 0g 0 0 0 0 0 0 0 0 0 4. 0 0 0 0 0 1 0 0 0 0c 0 1 0 0 0 0 0 0 0 0s 0 0 2 0 0 0 0 0 0 0d 0 0 0 3 0 0 0 0 0 0n 0 0 0 0 4 0 0 0 0 0. 0 0 0 0 0 5 0 0 0 0n 0 0 0 0 1 0 0 0 0 0e 0 0 0 0 0 0 0 0 0 0t 0 0 0 0 0 0 0 0 0 0max substr length:5这是程序的输出结果,请注意红色字体时间空间复杂度分析如果用n,m表示两个字符串的长度的话,那么算法的时间复杂度为O(n*m),空间复杂度也为O(n*m)附:完整的源程序g++编译通过#include <stdio.h>#include <string.h>void print_table(char *str1,char *str2,int **pf) {int i,j,row,col;row = strlen(str1);col = strlen(str2);printf("\t\t");for (i=0; i<col; i++)printf("%c\t",str2[i]);for (i=0; i<=row; i++){for (j=0; j<=col; j++){if (j == 0){printf("\n");if (i)printf("%c\t",str1[i-1]);elseprintf("\t");}printf("%d\t",pf[i][j]);}}}int commstr(char *str1, char *str2)/* 返回str1,str2的最长公共之串长度*/{int len1=strlen(str1),len2=strlen(str2),row,col,max=0;int **pf = new int*[len1+1];//动态分配一个二维数组作为辅助空间 for (row=0; row<len1+1; row++)pf[row] = new int[len2+1];//数组赋初值for (row=0; row<len1+1; row++)pf[row][0] = 0;for (col=0; col<len2+1; col++)pf[0][col] = 0;for (row=1; row<=len1; row++)for (col=1;col<=len2; col++){if (str1[row-1] == str2[col-1]){pf[row][col] = pf[row-1][col-1] + 1;max = pf[row][col] > max ? pf[row][col] : max; }elsepf[row][col] = 0;}print_table(str1,str2,pf);//空间回收for (row=0; row<len1+1; row++)delete[] pf[row];delete[] pf;return max;}int main(int argc,char **argv){if (argc >= 3){printf("String:\n\t1. %s\n\t2. %s\n",argv[1],argv[2]);printf("\nmax substr length:%d\n",commstr(argv[1],argv[2])); }return 0;}。
算法55----最长⼦序列【动态规划】⼀、题⽬:最长公共⼦序列:给定两个字符串,求解这两个字符串的最长公共⼦序列(Longest Common Sequence)。
⽐如字符串L:BDCABA;字符串S:ABCBDAB 则这两个字符串的最长公共⼦序列长度为4,最长公共⼦序列是:BCBA思路:动态规划:时间O(n * m),空间O(n * m)创建 DP数组C[i][j]:表⽰⼦字符串L【:i】和⼦字符串S【:j】的最长公共⼦序列个数。
状态⽅程:个数代码:def LCS(L,S):if not L or not S:return""dp = [[0] * (len(L)+1) for i in range(len(S)+1)]for i in range(len(S)+1):for j in range(len(L)+1):if i == 0 or j == 0:dp[i][j] = 0else:if L[j-1] == S[i-1]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = max(dp[i-1][j],dp[i][j-1])return dp[-1][-1]L = 'BDCABA'S = 'ABCBDAB'LCS(L,S)最长⼦序列代码:设置⼀个标志def LCS(L,S):if not L or not S:return""res = ''dp = [[0] * (len(L)+1) for i in range(len(S)+1)]flag = [['left'] * (len(L)+1) for i in range(len(S)+1)]if i == 0 or j == 0:dp[i][j] = 0flag [i][j] = '0'else:if L[j-1] == S[i-1]:dp[i][j] = dp[i-1][j-1] + 1flag[i][j] = 'ok'else:dp[i][j] = max(dp[i-1][j],dp[i][j-1])flag[i][j] = 'up'if dp[i][j] == dp[i-1][j] else'left' return dp[-1][-1],flagdef printres(flag,L,S):m = len(flag)n = len(flag[0])res = ''i , j = m-1 , n-1while i > 0 and j > 0:if flag[i][j] == 'ok':res += L[j-1]i -= 1j -= 1elif flag[i][j] == 'left':j -= 1elif flag[i][j] == 'up':i -= 1return res[::-1]L = 'BDCABA'S = 'ABCBDAB'num,flag = LCS(L,S)res = printres(flag,L,S)⼆、题⽬:最长递增⼦序列8},则其最长的单调递增⼦序列为{5,6,7,8},长度为4.解法⼀:最长公共⼦序列:O(N^2)这个问题可以转换为最长公共⼦序列问题。
动态规划解最长公共子序列问题动态规划主要针对最优化问题,它的决策是全面考虑不同的情况分别进行决策,,最后通过多阶段决策逐步找出问题的最终解.当各个阶段采取决策后,会不断决策出新的数据,直到找到最优解.每次决策依赖于当前状态,又随机引起状态的转移.一个决策序列就是在变化的状态中产生出来的,故有”动态”的含义.所以,这种多阶段最优化决策解决问题的过程称为动态规划.一问题的描述与分析字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干字符(可能一个也不去掉)后形成的字符序列..令给定的字符序列X=”x0,x1,x2,…xm-1”,序列Y=”y0,y1,…yk-1”是X的子序列,存在X的一个严格递增下标序列i=i0,i1,i2,…ik-1,使得对所有的j=0,1,2,…k-1,有xi=yi。
例如X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。
给定两个序列A和B,称序列Z是A和B公共子序列,是指Z同是A和B的子序列。
求最长公共子序列。
若A的长度为m,B的长度为n,则A的子序列有2*m-1个,B的子序列有2*n-1个。
采用枚举法分别对A和B的所以子序列一一检查,最终求出最长公共子序列。
如此比较次数(2*2n)接近指数阶,当n较大时,算法太耗时,不可取。
所以要全面考虑不同的情况分别进行决策,,最后通过多阶段决策逐步找出问题的最终解.当各个阶段采取决策后,会不断决策出新的数据,直到找到最优解。
二、算法设计(或算法步骤)A=”a0,a1,a2,……am-1”,B=”b0,b1,b2,……bn-1”,且Z=”z0,z1,z2……zk-1”,为她们的最长公共子序列。
不难证明有一下结论:(1)如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,z2,……zk-2”是“a0,a1,a2,……am-2”和“b0,b1,b2,……bn-2”的一个最长公共子序列;(2)如果am-1!=bn-1,则若zk-1!=am-1,则“z0,z1,z2,……zk-1”是“a0,a1,a2,……am-2”和”b0,b1,b2,……bn-1”的一个最长公共子序列。
最长公共子序列算法利用的算法最长公共子序列算法通常使用动态规划算法来实现。
动态规划是一种将问题拆分成子问题并按顺序解决的算法。
在最长公共子序列算法中,我们将两个序列分别称为序列X和序列Y。
我们定义一个二维数组dp,其中dp[i][j]表示序列X的前i个元素和序列Y的前j个元素的最长公共子序列的长度。
动态规划的递推关系如下:1. 如果X[i]等于Y[j],则dp[i][j]等于dp[i-1][j-1]加1。
即序列X的前i个元素和序列Y的前j个元素的最长公共子序列的长度等于序列X的前i-1个元素和序列Y的前j-1个元素的最长公共子序列的长度加1。
2. 如果X[i]不等于Y[j],则dp[i][j]等于dp[i-1][j]和dp[i][j-1]中的较大值。
即序列X的前i个元素和序列Y的前j个元素的最长公共子序列的长度等于序列X的前i-1个元素和序列Y的前j个元素的最长公共子序列的长度,或者序列X的前i个元素和序列Y的前j-1个元素的最长公共子序列的长度中的较大值。
通过填充dp数组,最终dp[X.length][Y.length]即为序列X和序列Y 的最长公共子序列的长度。
然后,我们可以通过回溯dp数组来找到最长公共子序列。
从dp[X.length][Y.length]开始,根据上述递推关系,如果dp[i][j]等于dp[i-1][j-1]加1,则说明X[i]等于Y[j],将X[i]加入最长公共子序列中,并继续回溯dp[i-1][j-1];如果dp[i][j]等于dp[i-1][j],则说明X[i]不在最长公共子序列中,回溯dp[i-1][j];如果dp[i][j]等于dp[i][j-1],则说明Y[j]不在最长公共子序列中,回溯dp[i][j-1]。
最终,通过回溯,我们可以得到序列X和序列Y的最长公共子序列。
最大公共子序列的算法
最大公共子序列(LCS)问题是一个经典的计算机科学问题,它涉及到两个序列的匹配问题。
给定两个序列,找出最长的公共子序列,使得这个子序列在两个输入序列中都出现。
下面是一种常用的动态规划算法来解决这个问题:
1.初始化两个矩阵,分别表示两个输入序列的长度。
假设输入序列A的长度为m,输入序列B的长度为n,那么这两个矩阵的大小都为m x n。
2.填充矩阵的第一行和第一列。
对于矩阵的第一行,所有的元素都设置为0,因为子序列不能在原序列之前开始;对于矩阵的第一列,所有的元素都设置为1,因为第一个字符总是匹配的。
3.从矩阵的第二行和第二列开始,遍历矩阵的每一个元素。
如果当前元素对应的两个字符相同,那么该元素的值就等于左上角元素的值加1;否则,该元素的值就等于左上角元素的值。
4.填充完矩阵之后,最大公共子序列的长度就等于矩阵右下角的元素的值。
5.回溯矩阵,从右下角开始,找到最长公共子序列。
如果当前元素的值等于左上角元素的值加1,那么将当前字符添加到最长公共子序列中,然后继续向左上方移动;如果当前元素的值等于左上角元素的值,那么不将当前字符添加到最长公共子序列中,继续向左上方移动。
6.当回溯到左上角时,最长公共子序列的长度就等于左上方元素的值。
这个算法的时间复杂度是O(mn),其中m和n分别是两个输入序列的长度。
在实际应用中,如果输入序列的长度很大,可以考虑使用其他优化算法来提高效率。
最长公共子序列动态规划算法下面我们将详细介绍使用动态规划算法求解最长公共子序列的过程。
首先,我们定义一个二维数组dp,其中dp[i][j]表示序列1的前i个字符和序列2的前j个字符的最长公共子序列的长度。
接下来,我们需要确定动态规划的状态转移方程。
对于dp[i][j],我们有以下两种情况:1. 如果序列1的第i个字符和序列2的第j个字符相等,即seq1[i] == seq2[j],那么dp[i][j]就等于dp[i-1][j-1]加1,表示当前字符可以构成最长公共子序列的一部分。
2. 如果序列1的第i个字符和序列2的第j个字符不相等,即seq1[i] != seq2[j],那么dp[i][j]就等于dp[i-1][j]和dp[i][j-1]中的较大值,表示当前字符不能构成最长公共子序列,需要继续考察前面的字符。
根据以上分析,我们可以得到状态转移方程为:```if seq1[i] == seq2[j]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = max(dp[i-1][j], dp[i][j-1])```其中,max(函数表示取两个值的较大值。
接下来,我们需要确定初始条件。
对于dp数组的第一行和第一列,由于没有前一个字符,我们无法进行状态转移,因此需要将它们初始化为0。
最后,我们需要根据状态转移方程和初始条件,依次计算dp数组的所有值。
最终,dp数组的最后一个元素dp[m][n]就表示序列1的前m个字符和序列2的前n个字符的最长公共子序列的长度。
通过确定状态转移方程、初始条件和计算过程,我们可以得到求解最长公共子序列问题的动态规划算法。
下面是具体的算法步骤:1. 根据待求解的两个序列seq1和seq2的长度,创建一个二维数组dp,其中dp[i][j]表示序列1的前i个字符和序列2的前j个字符的最长公共子序列的长度。
2. 初始化dp数组的第一行和第一列为0。
c语言求解最长公共子序列问题的算法最长公共子序列问题可以使用动态规划算法求解,以下是一个使用动态规划算法求解最长公共子序列的C语言代码:#include<stdio.h>#include<stdlib.h>#include<string.h>// 求解最长公共子序列长度的函数int LCS(char* s1, char* s2, int m, int n){int i, j;int **dp = (int**)malloc((m+1) * sizeof(int*)); // 创建动态规划表dp for(i=0; i<=m; i++){dp[i] = (int*)malloc((n+1) * sizeof(int));// 初始化动态规划表的第一行和第一列为0dp[i][0] = 0;}for(j=0; j<=n; j++){dp[0][j] = 0;}// 根据动态规划公式填充动态规划表for(i=1; i<=m; i++){for(j=1; j<=n; j++){if(s1[i-1] == s2[j-1]) // 当前字符相等{dp[i][j] = dp[i-1][j-1] + 1; // 状态转移方程}else // 当前字符不相等{dp[i][j] = (dp[i][j-1] > dp[i-1][j]) ? dp[i][j-1] : dp[i-1][j]; // 状态转移方程}}}int result = dp[m][n]; // 最长公共子序列的长度// 释放动态规划表for(i=0; i<=m; i++){free(dp[i]);}free(dp);return result;}int main(){// 输入两个字符串char s1[100], s2[100];printf("请输入字符串1:");scanf("%s", s1);printf("请输入字符串2:");scanf("%s", s2);int m = strlen(s1);int n = strlen(s2);int result = LCS(s1, s2, m, n); // 求解最长公共子序列的长度printf("最长公共子序列的长度为:%d\n", result);return 0;}该算法的基本思路是,首先创建一个二维的动态规划表dp,其中dp[i][j]表示s1的前i个字符和s2的前j个字符的最长公共子序列的长度。
最长公共子序列例题以下是一个关于最长公共子序列的例题:给定两个序列 X = { x1, x2, ..., xm } 和 Y = { y1, y2, ..., yn },求 X 和 Y 的最长公共子序列。
举例:X = { a, b, c, b, d, a, b }Y = { b, d, c, a, b, a }最长公共子序列为 LSC = { b, c, b, a }。
解题思路:最长公共子序列问题具有最优子结构性质,可以使用动态规划求解。
设 X 和Y 的最长公共子序列为 Z,其中 Z 的长度为 k。
那么可以用一个二维数组c[m+1][n+1] 来存储 X[i] 和 Y[j] 的最长公共子序列的长度,其中 i 和 j 分别为 X 和 Y 的下标。
根据最优子结构性质,如果 X[i] = Y[j],那么 c[i][j] = c[i-1][j-1] + 1;如果 X[i] != Y[j],那么 c[i][j] = max(c[i-1][j], c[i][j-1])。
最终,c[m][n] 就是 X 和 Y 的最长公共子序列的长度。
通过动态规划求解最长公共子序列的具体过程如下:1.初始化数组 c,将所有元素初始化为 0;2.遍历 X 和 Y 的每个元素,对于每个元素 X[i] 和 Y[j],如果 X[i] == Y[j],则 c[i][j] = c[i-1][j-1] + 1;否则,c[i][j] = max(c[i-1][j], c[i][j-1]);3.在 c[m][n] 中存储的就是 X 和 Y 的最长公共子序列的长度;4.从 c 数组中回溯出最长公共子序列。
具体做法是从 c[m][n] 开始,如果c[i][j] == c[i-1][j-1] + 1,说明 X[i] 和 Y[j] 在最长公共子序列中是相邻的,因此最长公共子序列就是 X[i], Y[j]。
然后继续回溯,将 X[i+1], Y[j+1] 加入最长公共子序列中,直到回溯到 c[0][0]。
动态规划解最长公共子序列问题2009-05-30 21:28 36702人阅读评论(36) 收藏举报c算法动态规划法经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题。
简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加。
为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存于该数组中,这就是动态规划法所采用的基本方法。
【问题】求两字符序列的最长公共字符子序列问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。
令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X1的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj。
例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。
考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm-1”,并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。
不难证明有以下性质:(1)如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,…,zk-2”是“a0,a1,…,am-2”和“b0,b1,…,bn-2”的一个最长公共子序列;(2)如果am-1!=bn-1,则若zk-1!=am-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列;(3)如果am-1!=bn-1,则若zk-1!=bn-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列。
2这样,在找A和B的公共子序列时,如有am-1=bn-1,则进一步解决一个子问题,找“a0,a1,…,am-2”和“b0,b1,…,bm-2”的一个最长公共子序列;如果am-1!=bn-1,则要解决两个子问题,找出“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列和找出“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列,再取两者中较长者作为A和B的最长公共子序列。
动态规划解最长公共子序列问题动态规划主要针对最优化问题,它的决策是全面考虑不同的情况分别进行决策,,最后通过多阶段决策逐步找出问题的最终解.当各个阶段采取决策后,会不断决策出新的数据,直到找到最优解.每次决策依赖于当前状态,又随机引起状态的转移.一个决策序列就是在变化的状态中产生出来的,故有”动态”的含义.所以,这种多阶段最优化决策解决问题的过程称为动态规划.一问题的描述与分析字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干字符(可能一个也不去掉)后形成的字符序列..令给定的字符序列X=”x0,x1,x2,…xm-1”,序列Y=”y0,y1,…yk-1”是X的子序列,存在X的一个严格递增下标序列i=i0,i1,i2,…ik-1,使得对所有的j=0,1,2,…k-1,有xi=yi。
例如X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。
给定两个序列A和B,称序列Z是A和B公共子序列,是指Z同是A和B的子序列。
求最长公共子序列。
若A的长度为m,B的长度为n,则A的子序列有2*m-1个,B的子序列有2*n-1个。
采用枚举法分别对A和B的所以子序列一一检查,最终求出最长公共子序列。
如此比较次数(2*2n)接近指数阶,当n较大时,算法太耗时,不可取。
所以要全面考虑不同的情况分别进行决策,,最后通过多阶段决策逐步找出问题的最终解.当各个阶段采取决策后,会不断决策出新的数据,直到找到最优解。
二、算法设计(或算法步骤)A=”a0,a1,a2,……am-1”,B=”b0,b1,b2,……bn-1”,且Z=”z0,z1,z2……zk-1”,为她们的最长公共子序列。
不难证明有一下结论:(1)如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,z2,……zk-2”是“a0,a1,a2,……am-2”和“b0,b1,b2,……bn-2”的一个最长公共子序列;(2)如果am-1!=bn-1,则若zk-1!=am-1,则“z0,z1,z2,……zk-1”是“a0,a1,a2,……am-2”和”b0,b1,b2,……bn-1”的一个最长公共子序列。
(3)如果am-1!=bn-1,则若zk-1!=bn-1,则“z0,z1,z2,……zk-1”是“a0,a1,a2,……am-1”和“b0,b1,b2,……bn-2”的一个最长公共子序列。
如此找到了原问题与其子问题的递归关系。
基本存储结构是存储两个字符串及其最长公共子序列的3个一位数组。
当然要找出最长公共子序列,要存储当前最长公共子序列的长度和当前公共子序列的长度,而若只存储当前信息,最后只能求解最长公共子序列的长度,却不能找到最长公共子序列本身。
因此需建立一个(n+1)*(m+1)的二维数组c,c[i][j]存储序列“a0,a1,a2……ai-2”和“b0,b1,……bj-1”的最长公共子序列长度,由上递推关系分析,计算c[i][j]可递归的表述如下:(1)c[i][j]=0 如果i=0或j=0;(2)c[i][j]=c[i-1][j-1]+1 如果i,j>0,且a[i-1]=b[j-1](3)c[i][j]=max(c[i][j-1],c[i-1][j]) 如果i,j>0,且a[i-1]!=b[j-1]以此可写出计算两个序列的最长公共子序列的长度函数,最终求解出c[m][n].三、算法实现由二维数组c的递归定义,c[i][j]的结果仅依赖于c[i-1][j-1],c[i-1][j]和c[i][j-1].可以从c[m][n]开始,跟踪c[i][j]结果的产生过程,从而逆向构造最长公共子序列。
# include <stdio.h># include <string.h>#define N 100/*字符串的最大长度限制*/char a[ N ],/*第一个字符串*/b[ N ],/*第二个字符串*/str[ N ];/*用于存放a 与b的公共子序列*//*计算两个序列的最长公共子序列的长度*/int lcs_len( char *a, char *b, int c[][ N ] ){int m = strlen( a ),/*计算两个序列的长度*/n = strlen( b ),i,/*行指针*/j;/*列指针*/for( i = 0; i <= m; i++ ) c[ i ][ 0 ] = 0;/*j==0表示b串长度为0,无论a串多长,两者的公共子序列长度为0*/for( j = 1; j <= n; j++ ) c[ 0 ][ j ] = 0;/*根据上一个类推*/for( i = 1; i <= m; i++ )/*开始递推*/for( j = 1; j <= n; j++ )/*若两序列的最后一个字符相同,那么公共子序列长度为去掉这最后一个字符后新生成的两个串的公共子序列长度+1*/if( a[ i - 1 ] == b[ j - 1 ]){ c[ i ][ j ] = c[ i - 1 ][ j - 1 ] + 1;printf("\nc[ %d ][ %d ] = c[ %d - 1 ][ %d - 1 ] + 1\n", i, j, i, j );}/**/else if( c[ i - 1 ][ j ] >= c[ i ][ j -1 ] ){ c[ i ][ j ] = c[ i - 1 ][ j ];printf("\nc[ %d ][ %d ] = c[ %d - 1 ][ %d ]\n", i, j, i, j );}/*若两序列最后一个字符不同,那么他们最大子序列的长度为c[ i - 1][j]和c[i][j-1]中较大的一个*/else{c[ i ][ j ] = c[ i ][ j -1 ];printf("\nc[ %d ][ %d ] = c[ %d ][ %d - 1]\n", i, j, i, j);}/*调试:将生成的数组方阵显示出来,m行,n列*/printf("\n");printf(" ");for( j = 0; j <= n; j++ )printf("%d, ", j );/*显示列标号*/printf("\n");for( i = 0; i <= m; i++ ){printf("%d: ", i );/*显示行标号*/for( j = 0; j <= n; j++ )printf("%d, ", c[ i ][ j ] );printf("\n");/*一行显示完,换下一行*/}return c[ m ][ n ];/*结果:a与b的最大子序列长度存在c[m][n]中*/}/*构造最长子序列函数*/char *build_lcs( char s[], char *a, char *b ){/*根据lcs_len()函数计算的结果,倒推出最长子序列,结果放在s[]中*/int k,/*a与b最长子序列的长度*/i = strlen( a ),/*a串长度*/j = strlen( b ),/*b*/c[ N ][ N ];/*存放全部的计算过程,动态规划,体现在这个地方,中间计算结果都在这里*/k = lcs_len( a, b, c );/*将c[][]传给lcs_len()计算并求出长度,将中间结果放在c[][]中*/s[ k ] = '\0';/*s串的结束标记*/while( k > 0 )/*开始倒推*/if( c[ i ][ j ] == c[ i - 1 ][ j ] ) i --;else if( c[ i ][ j ] == c[ i ][ j -1 ]) j--;else{ s[ --k ] = a[ i - 1 ];/*将一个公共字符存入s中*/i--;j--;}return s;}/*测试程序*/void main(){printf("Enter two string(<%d)!\n", N );scanf( "%s%s", a,b );printf("LCS = %s\n", build_lcs( str, a, b ));}以X=”ABCBDAB”与Y=”BDCABA”为例,两字符串算法实现求解最长公共子序列的长度和最长公共子序列的求解过程。
Enter two string(<100)!a,b,ca,b,c,dc[ 1 ][ 1 ] = c[ 1 - 1 ][ 1 - 1 ] + 1c[ 1 ][ 2 ] = c[ 1 ][ 2 - 1]c[ 1 ][ 3 ] = c[ 1 ][ 3 - 1]c[ 1 ][ 4 ] = c[ 1 ][ 4 - 1]c[ 1 ][ 5 ] = c[ 1 ][ 5 - 1]c[ 1 ][ 6 ] = c[ 1 ][ 6 - 1]c[ 1 ][ 7 ] = c[ 1 ][ 7 - 1]c[ 2 ][ 2 ] = c[ 2 - 1 ][ 2 - 1 ] + 1 c[ 2 ][ 3 ] = c[ 2 ][ 3 - 1]c[ 2 ][ 4 ] = c[ 2 - 1 ][ 4 - 1 ] + 1 c[ 2 ][ 5 ] = c[ 2 ][ 5 - 1]c[ 2 ][ 6 ] = c[ 2 - 1 ][ 6 - 1 ] + 1 c[ 2 ][ 7 ] = c[ 2 ][ 7 - 1]c[ 3 ][ 1 ] = c[ 3 - 1 ][ 1 ]c[ 3 ][ 2 ] = c[ 3 - 1 ][ 2 ]c[ 3 ][ 3 ] = c[ 3 - 1 ][ 3 - 1 ] + 1 c[ 3 ][ 4 ] = c[ 3 ][ 4 - 1]c[ 3 ][ 5 ] = c[ 3 ][ 5 - 1]c[ 3 ][ 6 ] = c[ 3 ][ 6 - 1]c[ 3 ][ 7 ] = c[ 3 ][ 7 - 1]c[ 4 ][ 1 ] = c[ 4 - 1 ][ 1 ]c[ 4 ][ 2 ] = c[ 4 - 1 ][ 2 - 1 ] + 1 c[ 4 ][ 3 ] = c[ 4 - 1 ][ 3 ]c[ 4 ][ 4 ] = c[ 4 - 1 ][ 4 - 1 ] + 1 c[ 4 ][ 5 ] = c[ 4 ][ 5 - 1]c[ 4 ][ 6 ] = c[ 4 - 1 ][ 6 - 1 ] + 1 c[ 4 ][ 7 ] = c[ 4 ][ 7 - 1]c[ 5 ][ 1 ] = c[ 5 - 1 ][ 1 ]c[ 5 ][ 3 ] = c[ 5 - 1 ][ 3 ]c[ 5 ][ 4 ] = c[ 5 - 1 ][ 4 ]c[ 5 ][ 5 ] = c[ 5 - 1 ][ 5 - 1 ] + 1 c[ 5 ][ 6 ] = c[ 5 ][ 6 - 1]c[ 5 ][ 7 ] = c[ 5 ][ 7 - 1]0, 1, 2, 3, 4, 5, 6, 7,0: 0, 0, 0, 0, 0, 0, 0, 0,1: 0, 1, 1, 1, 1, 1, 1, 1,2: 0, 1, 2, 2, 2, 2, 2, 2,3: 0, 1, 2, 3, 3, 3, 3, 3,4: 0, 1, 2, 3, 4, 4, 4, 4,5: 0, 1, 2, 3, 4, 5, 5, 5,LCS = a,b,cPress any key to continue Enter two string(<100)!w,e,r,t,yw,r,t,ec[ 1 ][ 1 ] = c[ 1 - 1 ][ 1 - 1 ] + 1 c[ 1 ][ 2 ] = c[ 1 ][ 2 - 1]c[ 1 ][ 3 ] = c[ 1 ][ 3 - 1]c[ 1 ][ 4 ] = c[ 1 ][ 4 - 1]c[ 1 ][ 5 ] = c[ 1 ][ 5 - 1]c[ 1 ][ 6 ] = c[ 1 ][ 6 - 1]c[ 1 ][ 7 ] = c[ 1 ][ 7 - 1]c[ 2 ][ 1 ] = c[ 2 - 1 ][ 1 ]c[ 2 ][ 2 ] = c[ 2 - 1 ][ 2 - 1 ] + 1 c[ 2 ][ 3 ] = c[ 2 ][ 3 - 1]c[ 2 ][ 4 ] = c[ 2 - 1 ][ 4 - 1 ] + 1 c[ 2 ][ 5 ] = c[ 2 ][ 5 - 1]c[ 2 ][ 6 ] = c[ 2 - 1 ][ 6 - 1 ] + 1 c[ 2 ][ 7 ] = c[ 2 ][ 7 - 1]c[ 3 ][ 1 ] = c[ 3 - 1 ][ 1 ]c[ 3 ][ 2 ] = c[ 3 - 1 ][ 2 ]c[ 3 ][ 3 ] = c[ 3 - 1 ][ 3 ]c[ 3 ][ 4 ] = c[ 3 - 1 ][ 4 ]c[ 3 ][ 5 ] = c[ 3 - 1 ][ 5 ]c[ 3 ][ 6 ] = c[ 3 - 1 ][ 6 ]c[ 3 ][ 7 ] = c[ 3 - 1 ][ 7 - 1 ] + 1 c[ 4 ][ 1 ] = c[ 4 - 1 ][ 1 ]c[ 4 ][ 2 ] = c[ 4 - 1 ][ 2 - 1 ] + 1 c[ 4 ][ 3 ] = c[ 4 - 1 ][ 3 ]c[ 4 ][ 4 ] = c[ 4 - 1 ][ 4 - 1 ] + 1 c[ 4 ][ 5 ] = c[ 4 ][ 5 - 1]c[ 4 ][ 6 ] = c[ 4 - 1 ][ 6 - 1 ] + 1 c[ 4 ][ 7 ] = c[ 4 - 1 ][ 7 ]c[ 5 ][ 1 ] = c[ 5 - 1 ][ 1 ]c[ 5 ][ 2 ] = c[ 5 - 1 ][ 2 ]c[ 5 ][ 3 ] = c[ 5 - 1 ][ 3 - 1 ] + 1 c[ 5 ][ 4 ] = c[ 5 - 1 ][ 4 ]c[ 5 ][ 5 ] = c[ 5 - 1 ][ 5 ]c[ 5 ][ 6 ] = c[ 5 - 1 ][ 6 ]c[ 5 ][ 7 ] = c[ 5 - 1 ][ 7 ]c[ 6 ][ 1 ] = c[ 6 - 1 ][ 1 ]c[ 6 ][ 2 ] = c[ 6 - 1 ][ 2 - 1 ] + 1 c[ 6 ][ 3 ] = c[ 6 - 1 ][ 3 ]c[ 6 ][ 4 ] = c[ 6 - 1 ][ 4 - 1 ] + 1 c[ 6 ][ 5 ] = c[ 6 ][ 5 - 1]c[ 6 ][ 6 ] = c[ 6 - 1 ][ 6 - 1 ] + 1 c[ 6 ][ 7 ] = c[ 6 ][ 7 - 1]c[ 7 ][ 1 ] = c[ 7 - 1 ][ 1 ]c[ 7 ][ 2 ] = c[ 7 - 1 ][ 2 ]c[ 7 ][ 3 ] = c[ 7 - 1 ][ 3 ]c[ 7 ][ 4 ] = c[ 7 - 1 ][ 4 ]c[ 7 ][ 5 ] = c[ 7 - 1 ][ 5 - 1 ] + 1 c[ 7 ][ 6 ] = c[ 7 ][ 6 - 1]c[ 7 ][ 7 ] = c[ 7 ][ 7 - 1]c[ 8 ][ 1 ] = c[ 8 - 1 ][ 1 ]c[ 8 ][ 2 ] = c[ 8 - 1 ][ 2 - 1 ] + 1 c[ 8 ][ 3 ] = c[ 8 - 1 ][ 3 ]c[ 8 ][ 4 ] = c[ 8 - 1 ][ 4 - 1 ] + 1 c[ 8 ][ 5 ] = c[ 8 - 1 ][ 5 ]c[ 8 ][ 6 ] = c[ 8 - 1 ][ 6 - 1 ] + 1 c[ 8 ][ 7 ] = c[ 8 ][ 7 - 1]c[ 9 ][ 1 ] = c[ 9 - 1 ][ 1 ]c[ 9 ][ 2 ] = c[ 9 - 1 ][ 2 ]c[ 9 ][ 3 ] = c[ 9 - 1 ][ 3 ]c[ 9 ][ 4 ] = c[ 9 - 1 ][ 4 ]c[ 9 ][ 5 ] = c[ 9 - 1 ][ 5 ]c[ 9 ][ 6 ] = c[ 9 - 1 ][ 6 ]c[ 9 ][ 7 ] = c[ 9 - 1 ][ 7 ]0, 1, 2, 3, 4, 5, 6, 7,0: 0, 0, 0, 0, 0, 0, 0, 0,1: 0, 1, 1, 1, 1, 1, 1, 1,2: 0, 1, 2, 2, 2, 2, 2, 2,3: 0, 1, 2, 2, 2, 2, 2, 3,4: 0, 1, 2, 2, 3, 3, 3, 3,5: 0, 1, 2, 3, 3, 3, 3, 3,6: 0, 1, 2, 3, 4, 4, 4, 4,7: 0, 1, 2, 3, 4, 5, 5, 5,8: 0, 1, 2, 3, 4, 5, 6, 6,9: 0, 1, 2, 3, 4, 5, 6, 6,LCS = w,r,t,Press any key to continue。