AcWing987 最长公共子序列
一般对于这种dp,都会设计两维,表示a中前i个和b中前j个能表示的最长长度是多少
那么考虑对集合进行划分
我们可以想到,当遍历到i,j时,有四种可能,一种是都不选,一种是都选,还有两种是选一个
对于都不选,那么就等于f[i-1][j-1],对于都选,是f[i-1][j-1]+1,前提是相等
剩下两种情况,直接用dp状态无法表示,但是我们可以用f[i-1][j],f[i][j-1]表示,因为这两个包含我们需要求取的状态,虽然会有很多重复的情况,但是没有关系,求最大最小允许集合存在交叉,只要不漏就行
而对于都不选的情况,其实就包含在这两种情况里面,所以第一种可以省略,当然也可以不省略
#include<iostream> #include<cstring> using namespace std; const int N=1e5+10; char a[N]; char b[N]; int f[1010][1010]; int main(){ int n,m; cin>>n>>m; scanf("%s",a+1); scanf("%s",b+1); int i,j; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ f[i][j]=max(f[i-1][j],f[i][j-1]); if(a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1); } } cout<<f[n][m]<<endl; return 0; }
没有人不辛苦,只有人不喊疼