个人博客
www.tothefor.com
蓝桥杯复习知识点汇总
纸上得来终觉浅,绝知此事要躬行。路漫漫其修远兮,吾将上下而求索!知识是经过历史的巨人沉淀下来的,别总想着自己能够快速学会,多花点时间去看看,也许会发现些不同的东西。你能快速学会的、觉得简单的东西,对于别人来说也是一样的。人外有人,天外有天。当努力到达了一定的程度,幸运自会与你不期而遇。
目录
求公共子序列长度
状态转移方程:
dp[i][j] = max(dp[i-1][j], dp[i][j-1],dp[i-1][j-1] + (A[i]==B[j] ? 1 : 0))
,表示在这三种状态中取到最大值。
(1)第一种状态表示不录入第一个序列的第i个字符时的最长公共子序列,
(2)第二种状态表示不录入第二个序列的第j个字符时的最长公共子序列,
(3)第三种状态表示第一个序列的前i-1个字符与第二个序列前j-1个字符的公共子序列加上最后一个字符的录入状态,如果最后的一个字符相等则录入,状态为1,否则不录入,状态为0。
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/
public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);
public static int maxd = 10000+7;
public static int INF = 0x3f3f3f3f;
public static int mod = 998244353;
public static int[][] dp = new int[maxd][maxd]; //dp[i][j]表示串a的前i个和串b的前j个的公共子序列的最长长度
public static void lcs(char[] x,char[] y){
int lenx = x.length;
int leny = y.length;
for(int i=1;i<=lenx;++i){
for(int j=1;j<=leny;++j){
if(x[i-1]==y[j-1]) dp[i][j] = dp[i-1][j-1]+1;
else dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]); //当当前对应位置不等时,就看是不要串a的,还是不要串b中的
}
}
}
public static void main(String[] args) throws Exception {
String s1 = nextString();
String s2 = nextString();
lcs(s1.toCharArray(),s2.toCharArray());
System.out.println(dp[s1.length()][s2.length()]);
closeAll();
}
public static void cinInit(){
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers();
}
public static int nextInt() throws Exception {
cin.nextToken();
return (int) cin.nval;
}
public static long nextLong() throws Exception {
cin.nextToken();
return (long) cin.nval;
}
public static double nextDouble() throws Exception {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws Exception {
cin.nextToken();
return cin.sval;
}
public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}
测试数据
输入:
abcfbc abfcab
programming contest
abcd mnp
输出:
4
2
0
求公共子序列
根据动态规划的状态,来判断我们要求得的序列中的字符有哪些。
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/
public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);
public static int maxd = 10000+7;
public static int INF = 0x3f3f3f3f;
public static int mod = 998244353;
public static int[][] dp = new int[maxd][maxd]; //dp[i][j]表示串a的前i个和串b的前j个的公共子序列的最长长度
public static void lcs(char[] x,char[] y){
int lenx = x.length;
int leny = y.length;
for(int i=1;i<=lenx;++i){
for(int j=1;j<=leny;++j){
if(x[i-1]==y[j-1]) dp[i][j] = dp[i-1][j-1]+1;
else dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]); //当当前对应位置不等时,就看是不要串a的,还是不要串b中的
}
}
}
public static char[] LCSstr(char[] x,char[] y){
char[] ch = new char[maxd]; //用来存储公共子序列
int i = x.length;
int j = y.length;
int ind = 0; //记录公共子序列在ch数组中的下标,所以最后一定是等于公共子序列的长度的
while(i!=0 && j!=0){
if(x[i-1]==y[j-1]){
ch[ind++]=x[--i]; //因为字符数组是从0开始存储的,所以这里需要先减再存
j--;
}else if(dp[i][j-1]>dp[i-1][j]) { //因为前面lcs方法中,要的是dp较大值,所以要的是a串中的,b串中就可以少一个
j--;
}else if(dp[i][j-1]<=dp[i-1][j]){ //同理,这里要的是b串中的,所以让a串中少一个
i--;
}
}
return ch; //存储的最后结果是公共子序列的相反序列,因为是从后往前存的
}
public static void main(String[] args) throws Exception {
String s1 = nextString();
String s2 = nextString();
lcs(s1.toCharArray(),s2.toCharArray());
char[] ans = LCSstr(s1.toCharArray(),s2.toCharArray());
System.out.println(dp[s1.length()][s2.length()]);
int rlen = dp[s1.length()][s2.length()];
for(int i=rlen-1;i>=0;--i){
System.out.print(ans[i]);
}
System.out.println();
closeAll();
}
public static void cinInit(){
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers();
}
public static int nextInt() throws Exception {
cin.nextToken();
return (int) cin.nval;
}
public static long nextLong() throws Exception {
cin.nextToken();
return (long) cin.nval;
}
public static double nextDouble() throws Exception {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws Exception {
cin.nextToken();
return cin.sval;
}
public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}
测试数据
输入:
abcicba
abdkscab
输出:
4
abcb