![](https://img-blog.csdnimg.cn/d9beb2d45c1c48bab285b62fd814a6aa.png)
![](https://img-blog.csdnimg.cn/f4d9943461404feca4e644aca67a8012.png)
状态表示:f [ i ] [ j ] 表示a串的第i个, b串的第j个之前的最大公共子串长度
所以
状态转移有三种情况,取i不取j,取j不取i,取i又取j
在i,j指向的字符相同的情况下,直接转移到第三种状态就行
如果不相同 就要在前两种状态里选择长度更长的一种
状态计算:f [ i ] [ j ] = max ( f [ i - 1 ] [ j ] , f [ i ] [ j - 1 ] ) (a [ i ] ! = b [ j ])
f [ i ] [ j ] = max ( f [ i ] [ j ] , f [ i - 1 ] [ j - 1 ] + 1 )
#include <bits/stdc++.h>
using namespace std;
stack <char> stk;
char a[3050],b[3050];
int f[3050][3050];
char logo[3050][3050];//用来标记答案字符串
int main()
{
scanf("%s%s",a+1,b+1);
for(int i=1;i<=strlen(a+1);i++)
{
for(int j=1;j<=strlen(b+1);j++)
{
if(a[i]!=b[j])
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
}
else f[i][j]=max(f[i][j],f[i-1][j-1]+1),logo[i][j]='=';
}//相同字符会被打上标记
}
int x=1,y=1;
for(int i=1;i<=strlen(a+1);i++)
{
for(int j=1;j<=strlen(b+1);j++)
if(f[x][y]<f[i][j])x=i,y=j;
}
int temp=f[x][y];
for(int i=x;i>0;i--)
{
for(int j=y;j>0;j--)
{
if(logo[i][j]=='='&&f[i][j]==temp)temp--,stk.push(a[i]),i--;
}目标字符串不仅要带标记,每个字符所对应的长度还应递减
}
while(!stk.empty())cout<<stk.top(),stk.pop();
return 0;
}