算法分析与设计(六、最长公共子序列)
1、最长公共子序列问题
若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。
核心思想: 点击跳转链接.
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
char a[1001], b[1001];
int dp[1001][1001], len1, len2;
void lcs(int i, int j)
{
for (i = 1; i <= len1; i++)
{
for (j = 1; j <= len2; j++)
{
if (a[i - 1] == b[j - 1])
dp[i][j] = dp[i - 1][j - 1] + 1; //横坐标和纵坐标一致的话,dp[i][j]为左斜上对应的值加1
else if (dp[i - 1][j] > dp[i][j - 1])//横坐标和纵坐标不一致,上方和左方取大者
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = dp[i][j - 1];
}
}
}
void llcs()
{
int i, j, z = 0;
char c[1001];
memset(c, 0, sizeof(c));
i = len1, j = len2;
while (i != 0 && j != 0)
{
//横坐标和纵坐标一致的话,c素组的下一位为左斜上对应的横坐标或纵坐标
if (a[i - 1] == b[j - 1])
{
c[z++] = a[--i];
j--;
}
else if (dp[i - 1][j] < dp[i][j - 1])//上方的元素小于左方的话,横坐标减一,相当于左移
j--;
else if (dp[i][j - 1] <= dp[i - 1][j])//上方的元素小于左方的话,横坐标减一,相当于右移
i--;
}
for (i = z - 1; i >= 0; i--)
printf("%c", c[i]);
printf("\n");
}
int main()
{
while (true)
{
cin >> a ;
cin >> b;
memset(dp, 0, sizeof(dp));
len1 = strlen(a);
len2 = strlen(b);
lcs(len1, len2);
llcs();
}
return 0;
}
2、最大子字段和问题
https://www.cnblogs.com/cuphoria/p/9800147.html