写在前面:本文矩阵思路来源于这篇博文,感谢,侵删
flag矩阵思路来源于这篇博文,感谢,侵删
- 首先区分公共子序列和公共子串的区别
以loop和helloworld两个字符串为例。
子串必须是连续的字符串,
lo op,hel lo world,加粗斜体部分lo就是最长公共子串。
子序列就不一定连续了,
loo p,hel lo w o rld,加粗斜体部分loo就是最长公共子序列。 - 解题思路
还是和之前的最大连续子序列那篇博文思路一致,建立dp[i][j]二维数组,存储
表示以str1[i]作为末尾和str2[j]作为末尾的最长公共子序列和子串的长度,接下来就是递推公式了
对于子序列:
str1[i] == str2[j] 时,dp[i][j] = dp[i-1][j-1] +1
否则dp[i][j] = max(dp[i-1][j],dp[i][j-1])
对于子串:
由于子串必须是连续的,故dp[i][j]的值要想增加,只有str1[i] == str2[j]时的情况,dp[i][j] = dp[i-1][j-1] +1
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn = 100;
char str1[maxn];
char str2[maxn];
void LCS1(int** dp,int** flag,int n,int m)//最长公共子序列
{//flag矩阵的作用:标记dp[i][j]是如何得到的,方便最后回溯打印出最长子序列
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
if(str1[i] == str2[j])
{
dp[i][j] = dp[i-1][j-1]+1;
flag[i][j] = 1;
}
else if(dp[i-1][j] >= dp[i][j-1])
{
dp[i][j] = dp[i-1][j];
flag[i][j] = 2;
}
else if(dp[i-1][j] < dp[i][j-1])
{
dp[i][j] = dp[i][j-1];
flag[i][j] = 3;
}
printf("%d ",dp[i][j]);
}
printf("\n");
}
printf("%d\n",dp[n][m]);
}
void LCS2(int** dp,int** flag,int n,int m)//最长公共子串
{
int answer = 0;
int index = 0;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
if(str1[i] == str2[j])
{
dp[i][j] = dp[i-1][j-1]+1;
if(answer < dp[i][j])
{
answer = dp[i][j];
index = i;
}
}
}
}
printf("%d\n",answer);
char temp[maxn] = {""};
strncpy(temp,str1+index-answer+1,answer);//strncpy(想要的结果,起始地址(注意是地址,不是下标),长度)
printf("%s\n",temp);
}
void printLCS(int** dp,int** flag,int i,int j)
{
if(i == 0 || j== 0)
return ;
if(flag[i][j] == 1)
{
printLCS(dp,flag,i-1,j-1);
printf("%c ",str1[i]);
}
else if(flag[i][j] == 2)
printLCS(dp,flag,i-1,j);
else if(flag[i][j] == 3)
printLCS(dp,flag,i,j-1);
}
int main()
{
while(scanf("%s%s",str1+1,str2+1))
{
int n = strlen(str1+1);
int m = strlen(str2+1);
int **dp = (int**)malloc(sizeof(int*)*(n+1));
int **flag = (int**)malloc(sizeof(int*)*(n+1));
for(int i=0;i<=n;i++)
{
dp[i] = (int*)malloc(sizeof(int)*(m+1));
flag[i] = (int*)malloc(sizeof(int)*(m+1));
for(int j = 0;j<=m;j++)
dp[i][j] = 0;
}
LCS1(dp,flag,n,m);
printLCS(dp,flag,n,m);
free(dp);
free(flag);
}
return 0;
}