个人博客
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