**子序列与子串是两种不同的概念,千万不要混淆
给定字符串"tzjnbblmp";
子串是tzj,bbln等,子串是连在一起的
子序列是 tjn,nlmp等,但是子序列中的字符在字符串中不一定是连在一起的。
但是顺序在原串是不可颠倒的,比如pml既不是子序列,也不是子串
**
回到正文
什么是最长公共子序列
就是两个字符串的最长的公共的子序列
例如s1=“wxhnwq”,s2=“xppwyq”
最长子序列就是"xwq"
我们这样很容易看出来,但是计算机怎么知道呐,
动态规划吧;
设dp[i][j]表示长度为i的字符串与长度为j的字符串的最长的公共子序列
我们分两种情况
1.s1[i]==s2[j],我们就转移方程,dp[i][j]=dp[i-1][j-1]+1;意思是,以s1[i],s2[j]结尾的字符串的最大长度,肯定是前面的,在加上新加入的;
2.s1[i]!=s2[j],dp[i][j]=max(dp[i-1][j],dp[i][j-1];意思是,我们选择(长度为i与j-1)与(长度为i-1与j)的大的一个
我们递归求子序列是什么,在转移方程的同时,标记这一步是由i-1,j-1
还是i,j-1
还是i-1,j
来的
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6;
typedef long long ll;
int dp[1000][1000];
int vis[1001][1001];
char a[100];
char b[100];
void lcslength(int n,int m)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i]==b[j])
{
dp[i][j]=dp[i-1][j-1]+1;
vis[i][j]=1;
}
else if(dp[i-1][j]>dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
vis[i][j]=2;
}
else if(dp[i-1][j]<=dp[i][j-1])
{
dp[i][j]=dp[i][j-1];
vis[i][j]=3;
}
}
}
void lcs(int n,int m)
{
if(n==0 || m==0)
return;
if(vis[n][m]==1)
lcs(n-1,m-1),cout<<a[n]<<" ";
if(vis[n][m]==2)
lcs(n-1,m);
if(vis[n][m]==3)
lcs(n,m-1);
}
int main()
{
string s1,s2;
cin>>s1>>s2;
int n=s1.length();
int m=s2.length();
for(int i=1;i<=n;i++)
a[i]=s1[i-1];
for(int i=1;i<=m;i++)
b[i]=s2[i-1];
lcslength(n,m);
cout<<dp[n][m]<<endl;
lcs(n,m);
return 0;
}