动态规划最长公共子序列,最长公共子序列输出
第1篇问题描述2篇解决方案2.1动态编程3篇实现代码
1问题描述给定两个字符串(或数字序列)A和B,找一个字符串使这个字符串是A和B的最长公共部分(子序列可以是不连续的)
例如,字符串“sadstory”和“adminsorry”具有最长的公共子序列“adsory ”,长度为6。
2如果使用暴力解法,字符串A和B的长度分别设为N和M,那么两个字符串中的每个字符都有选择和不选择两种决策。得到两个子序列后,比较两个子序列需要O(max(n,m))的时间,所以总的时间复杂度会达到O,无法承受大数据的情况。
2.1动态规划dp[i][j]表示在字符串A的比特I和字符串B的比特J之前的LCS的长度(下标从1开始)
比如d[4][5]表示‘sads’和‘admin’的LCS长度,根据A [I]和B [I]可以分为两种判定:
1如果A[i]==B[j],字符串A和字符串B的LCS长度增加1位,即dp[i][j]=d[i -1][j -1] 1。例如,d[4][6]表示“sads”和“admins”的LCS长度。对比A[4]和B[6],发现两者都是‘s’,所以dp[4][6]等于dp[3][5] 1,如果A[i]就是32!=B[j],字符串A和字符串B的LCS长度不能扩展,所以dp[i][j]会继承dp[i-1][j]和dp[i][j-1]的较大值,即DP[I][j]=max { DP[I-1][j]发现 d 不等于 m ,所以d[3][3]不能在原来的基础上扩展。因此,它继承了 sa 和 adm 的LCS, sad 和 ad 的LCS的较大值,即 sad 和 ad 的LCS长度2。因此,得到状态转移方程:
边界:DP [I] [0]=DP [0] [J]=0 (0=I=N,0=J=M)
3实现代码#包含
#包括
#包括
使用STD:max;
const int MAXN=100
char A[MAXN],B[MAXN];
int DP[MAXN][MAXN];
int main(int argc,char const *argv[])
{
int n;
fgets(A 1,MAXN 1,stdin);//从A[1]存储
fgets(B 1,MAXN 1,stdin);
int lenA=strlen(a1)-1;//在由//strlen计算的fgets长度的末尾有一个额外的“\0”
int lenB=strlen(B1)-1;
//边界
for(int I=0;我=莉娜;我)
{
DP[I][0]=0;
}
for(int j=0;j=lenBj)
{
DP[0][j]=0;
}
//状态转换方程
for(int I=1;我=莉娜;我)
{
for(int j=1;j=lenBj)
{
if(A[i]==B[j]){
DP[I][j]=DP[I-1][j-1]1;
}否则{
dp[i][j]=max(dp[i-1][j],DP[I][j-1]);
}
}
}
printf(%d\n ,DP[lenA][lenB]);
返回0;
}
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。