AcWing-897.最长公共子序列
题目描述
给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数 N 和 M。
第二行包含一个长度为 N 的字符串,表示字符串 A。
第三行包含一个长度为 M 的字符串,表示字符串 B。
字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N,M≤1000
输入样例:
4 5
acbd
abedc
输出样例:
3
思路
状态表示f(i,j):
集
合
:
表
示
在
字
符
串
A
的
前
i
个
字
符
和
字
符
串
B
的
前
j
个
字
符
中
所
包
含
的
所
有
公
共
子
序
列
集合:表示在字符串A的前i个字符和字符串B的前j个字符中所包含的所有公共子序列
集合:表示在字符串A的前i个字符和字符串B的前j个字符中所包含的所有公共子序列
属 性 : M a x ( 最 长 的 子 序 列 ) 属性:Max(最长的子序列) 属性:Max(最长的子序列)
思路:
对
于
字
符
串
A
的
第
i
个
字
符
和
字
符
串
B
的
第
j
个
字
符
有
取
与
不
取
操
作
方
式
,
所
以
有
四
种
可
能
对于字符串A的第i个字符和字符串B的第j个字符有取与不取操作方式,所以有四种可能
对于字符串A的第i个字符和字符串B的第j个字符有取与不取操作方式,所以有四种可能
状态划分:
当
i
和
j
都
不
取
:
f
(
i
,
j
)
=
f
(
i
−
1
,
j
−
1
)
当i和j都不取:f(i,j) = f(i-1,j-1)
当i和j都不取:f(i,j)=f(i−1,j−1)
当 取 i 不 取 j : f ( i , j ) = f ( i , j − 1 ) 当取i不取j:f(i,j)=f(i,j-1) 当取i不取j:f(i,j)=f(i,j−1)
当 取 j 不 取 i : f ( i , j ) = f ( i − 1 , j ) 当取j不取i:f(i,j) = f(i-1,j) 当取j不取i:f(i,j)=f(i−1,j)
当 j 和 i 都 取 且 A ( i ) = B ( j ) , f ( i , j ) = f ( i − 1 , j − 1 ) + 1 当j和i都取且A(i)=B(j),f(i,j) = f(i-1,j-1)+1 当j和i都取且A(i)=B(j),f(i,j)=f(i−1,j−1)+1
有以上状态可知:
f
(
i
−
1
,
j
−
1
)
表
示
A
的
前
i
−
1
个
字
符
与
B
的
前
j
−
1
个
字
符
的
最
长
公
共
子
序
列
f(i-1,j-1)表示A的前i-1个字符与B的前j-1个字符的最长公共子序列
f(i−1,j−1)表示A的前i−1个字符与B的前j−1个字符的最长公共子序列
f ( i − 1 , j ) 表 示 A 的 前 i − 1 个 字 符 与 B 的 前 j 个 字 符 的 最 长 公 共 子 序 列 , 明 显 包 含 f ( i − 1 , j − 1 ) f(i-1,j)表示A的前i-1个字符与B的前j个字符的最长公共子序列,明显包含f(i-1,j-1) f(i−1,j)表示A的前i−1个字符与B的前j个字符的最长公共子序列,明显包含f(i−1,j−1)
所 以 : f ( i , j − 1 ) 和 f ( i − 1 , j ) 包 含 f ( i − 1 , j − 1 ) 且 有 交 叉 部 分 所以:f(i,j-1)和f(i-1,j)包含f(i-1,j-1)且有交叉部分 所以:f(i,j−1)和f(i−1,j)包含f(i−1,j−1)且有交叉部分
综上:共只有三种状态,因为是求最大值,所以有重合对答案并没有影响
核心代码
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
if (A[i] == B[j]) f[i][j] = Math.max(f[i][j], f[i - 1][j - 1] + 1);
}
}
完整代码
package acWing897;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
static int N = 1010;
static int f[][] = new int[N][N];
static int n,m;
static char A[] = new char[N],B[] = new char[N];
public static void main(String[] args) throws Exception{
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String str[] = bf.readLine().split(" ");
n = Integer.parseInt(str[0]);m = Integer.parseInt(str[1]);
A = ("0"+bf.readLine()).toCharArray();
B = ("0"+bf.readLine()).toCharArray();
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
if (A[i] == B[j]) f[i][j] = Math.max(f[i][j], f[i - 1][j - 1] + 1);
}
}
System.out.println(f[n][m]);
}
}