最长公共子序列

最长公共子序列

题目描述

给定长度为 \(n\) 的数组 \(a\),长度为 \(m\) 的数组 \(b\),求其最长公共子序列长度


DP

\(f[i][j]\) 表示 \(a\)\(i\) 项和 \(b\)\(j\) 项的最长公共子序列长度

因为如果我们要在序列尾巴上加元素是不跟前面选了什么有关系的,所以没有后效性,珂以 DP

很显然我们可以选择不选 \(a_i\),所以可以转移 \(f[i-1][j]\)

我们亦可以不选 \(b_j\),所以可以转移 \(f[i][j-1]\)

如果要选 \(a_i\)\(b_j\) 的话,必须满足 \(a_i=b_j\),因为是公共子序列,我们将 \(a_i\)\(b_j\) 加进去,所以可以转移 \(f[i-1][j-1]+1\)

对于既不选 \(a_i\) 也不选 \(b_j\) 的状态,可以不用转移,因为肯定不会优于第三种,也已经在第一第二种中转移过了

综上,有

\[f[i][j]=max\{f[i-1][j],f[i][j-1],f[i-1,j-1]+1\} \]

其中第三个状态要满足 \(a_i=b_j\) 才能转移,\(1\leq i\leq lena,1\leq j\leq lenb\)

初始化 \(f[i][0]=0,f[0][j]=0\),目标是 \(f[lena][lenb]\)

code

for(int i=1; i<=n; ++i)
	for(int 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);
	}
posted @ 2023-08-12 22:38  Hypoxia571  阅读(2)  评论(0编辑  收藏  举报