import java.util.Scanner;
public class Main {
/**
* f(i,j)表示a[1~i]与b[1~j]之间的最长公共子序列长度
* 状态转移 f(i,j) = max(f(i-1,j-1),f(i-1,j),f(i,j-1),f(i-1,j-1)+1)
* 四个状态分别含义是:
* ①.a[i]!=b[j],所以f(i,j) = f(i-1,j-1)
* ②.a[1~i-1]与b[1~j]之间的最长公共子序列,分为b[j]属于公共子序列和不属于,在不属于时他就等于①
* ③.a[1~i]与b[1~j-1]之间的最长公共子序列,分为a[i]属于公共子序列和不属于,在不属于时他就等于①
* ④.a[i] = b[i],所以f(i,j) = f(i-1,j-1)+1
* 可以看出,②,③中包含了①状态,题目中要求计算最大值,因此在计算时只计算后三种即可
* f(i,j) = max(f(i-1,j),f(i,j-1),f(i-1,j-1)+1)
* (不重不漏原则,此时只需考虑不漏,计算最大值时可以重复)
*/
static int N = 1010;
static int f[][] = new int[N][N];
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
scanner.nextLine();
char[] a = (" "+scanner.nextLine()).toCharArray();
char[] b = (" "+scanner.nextLine()).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]);
}
}