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;
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12637008.html