蓝桥省赛 密码脱落 暴搜 记忆化搜索 区间DP

🍑 算法题解专栏


在这里插入图片描述
输入

ABDCDCBABC

输出

3

👨‍🏫 子序列 和 子串

🍤 串:连续
🍤 序列:允许不连续

🍑 记忆化搜索版

🍤 找不匹配的字符
import java.util.Scanner;

public class Main
{
	static int N = 1010;
	static String s;
	static int[][] f = new int[N][N];//记忆表
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		s = sc.next();
		System.out.println(dfs(0, s.length() - 1));
	}

// 返回 在 l-r 区间内,需要添加多少个字符才能使得字符串变成回文序列
	private static int dfs(int l, int r)
	{
		if (f[l][r] != 0)
			return f[l][r];

		if (l >= r)
			return 0;

		int res;
		if (s.charAt(l) != s.charAt(r)) // 只要不匹配,则需要加一个使得它匹配
// 			               添加一个右字符       添加左字符
			res = Math.min(dfs(l, r - 1) + 1, dfs(l + 1, r) + 1);
		else
		{
		  //  相等 即 回文 无需处理 --> 跳过
			res = dfs(l + 1, r - 1);
		}

		return f[l][r] = res;//记忆化搜索
	}
}

🍑 区间DP版

在这里插入图片描述

🍤 求区间内的最大回文子序列
import java.util.Scanner;

public class Main
{
	static int N = 1010;
	static String s;
	static int[][] f = new int[N][N];

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		s = sc.next();

		int n = s.length();
		for (int len = 1; len <= n; len++)// 枚举区间长度(大区间必定依赖与小区间来求解)
			for (int i = 0; i + len - 1 < n; i++)// 枚举左端点
			{
				int j = i + len - 1;// 计算右端点
				if (len == 1)
					f[i][j] = 1;
				else
				{
				//	f[i][j-1] 和 f[i+1][j] 的最大值 已经包含了 f[l+1][r-1]的最值
				//  
					f[i][j] = Math.max(f[i][j - 1], f[i + 1][j]);
					if (s.charAt(i) == s.charAt(j))
						f[i][j] = Math.max(f[i][j], f[i + 1][j - 1] + 2);
				}
			}

		int t = f[0][n - 1];// 这个是最大回文子序列
		System.out.println(n - t);
	}
}

👨‍🏫 参考题解

posted @ 2023-04-25 22:23  兑生  阅读(2)  评论(0编辑  收藏  举报  来源
Live2D