最长公共子序列
题目描述
给出1,2,…,n 的两个排列P1 和 P2 ,求它们的最长公共子序列。
输入格式
第一行是一个数 n。
接下来两行,每行为 n 个数,为自然数1,2,…,n 的一个排列。
输出格式
一个数,即最长公共子序列的长度。
题目分析
第一阶段定义dp数组
(1)考虑规模。两个序列的长度就是规模,因为是两个,所以需要两个维度来表示。
(2)考虑限制。这里的限制就是对应位置相等,可以在递推的时候进行限制。
(3)写dp数组。 d p [ i ] [ j ] dp[i][j] dp[i][j]表示的第一个序列前i个值和第二个序列前j个值对应的最长公共子序列
第二阶段推导状态转移方程
(1)如果 s 1 [ i ] = = s 2 [ j ] , d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 s1[i]==s2[j],dp[i][j]=dp[i-1][j-1]+1 s1[i]==s2[j],dp[i][j]=dp[i−1][j−1]+1
(1)如果 s 1 [ i ] ! = s 2 [ j ] s1[i]!=s2[j] s1[i]!=s2[j],那么我们就要从前一个状态的最大值里面转移过来,前一个状态有哪些呢? d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] dp[i-1][j],dp[i][j-1] dp[i−1][j],dp[i][j−1]就是它的前一个状态, d p [ i − 1 ] [ j − 1 ] dp[i-1][j-1] dp[i−1][j−1]不是,因为他距离 d p [ i − 1 ] [ j − 1 ] dp[i-1][j-1] dp[i−1][j−1]已经变化了2步。 d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) dp[i][j]=max(dp[i-1][j],dp[i][j-1]) dp[i][j]=max(dp[i−1][j],dp[i][j−1])
第三阶段写代码
(1)初始化。一开始长度是0。
(2)第一层for循环遍历规模,这里规模是两个维度表示的,所以也需要两层for循环。
(3)第二层for循环仍然遍历规模。文章来源:https://www.toymoban.com/news/detail-825112.html
题目代码
import java.io.IOException;
import java.util.Scanner;
public class Main{
public static void main(String[] args) throws NumberFormatException, IOException {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m=n;
int a[] = new int[n+1];
int b[] = new int[m+1];
int dp[][] = new int[n+1][m+1];
for(int i = 1;i <= n;i++)
a[i] = scanner.nextInt();
for(int i = 1;i <= m;i++)
b[i] = scanner.nextInt();
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= m;j++) {
if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
System.out.println(dp[n][m]);
}
}
在洛谷提交还是内存超限,离谱。
最长公共子串
题目分析
注意子串和子序列的差别,abcde中acd是一个子序列,但不是一个子串,abc是一个子串也是一个子序列。子串的要求要比子序列高。子串必须是连续的。那么这一点体现在哪里呢。体现在状态转移方程以及答案上。
第一阶段定义dp数组
(1)考虑规模。两个序列的长度就是规模,因为是两个,所以需要两个维度来表示。
(2)考虑限制。这里的限制就是对应位置相等,可以在递推的时候进行限制。
(3)写dp数组。 d p [ i ] [ j ] dp[i][j] dp[i][j]表示的第一个序列前i个值和第二个序列前j个值对应的最长公共子串
第二阶段推导状态转移方程
(1)如果 s 1 [ i ] = = s 2 [ j ] , d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 s1[i]==s2[j],dp[i][j]=dp[i-1][j-1]+1 s1[i]==s2[j],dp[i][j]=dp[i−1][j−1]+1
(1)如果 s 1 [ i ] ! = s 2 [ j ] , d p [ i ] [ j ] = 0 s1[i]!=s2[j],dp[i][j]=0 s1[i]!=s2[j],dp[i][j]=0
第三阶段写代码
(1)初始化。一开始长度是0。
(2)第一层for循环遍历规模,这里规模是两个维度表示的,所以也需要两层for循环。
(3)第二层for循环仍然遍历规模。
(4)答案。这里的 d p [ i ] [ j ] dp[i][j] dp[i][j]不一定是最终答案,答案要在过程中记录一个最大值。也就是所有dp值的最大值。 m a x ( d p [ i ] [ j ] ) max(dp[i][j]) max(dp[i][j])。文章来源地址https://www.toymoban.com/news/detail-825112.html
题目代码
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Main{
public static void main(String[] args) throws NumberFormatException, IOException {
Scanner scanner = new Scanner(System.in);
char a[];
char b[];
a = (" "+scanner.next()).toCharArray();
b = (" "+scanner.next()).toCharArray();
int n = a.length-1;
int m = b.length-1;
int dp[][] = new int[n+1][m+1];
int ans = 0;
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= m;j++) {
if(('0'<=a[i]&&a[i]<='9') || ('0'<=b[j]&&b[j]<='9')) continue;
if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1;
else dp[i][j] = 0;
ans = Math.max(ans, dp[i][j]);
}
}
System.out.println(ans);
}
}
到了这里,关于最长公共子序列和最长公共子串的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!