京东 2019实习生Java笔试题目2,求T串中最多的不相交Sm子串的个数

1. 题目

京东 2019实习生Java笔试题目2,求T串中最多的不相交Sm子串的个数_第1张图片
样例输入:

3
aa
b
ac
bbaac

样例输出:

3

样例解释:把T中字符从1开始编号,用[L,R]表示从第L个字符到第R个字符所构成的子串。一种选择子串的方法是[1,1],[2,2],[3,4] (b、b、aa) 一共3个串,另一种选法是[1,1],[2,2],[4,5] (b、b、ac) 一共也是3个串。注意不能同时选择子串[3,4],[4,5]因为它们相交了。


2. 解法

DP算法

dp[n] = max(dp[n-1], dp[n-len(Si)] + 1) , n >= len(Si), dp[0] = 0
# 1. n表示T串的前n个字符
# 2. 当有Si属于Sm的时候满足匹配,才会有max的第二个参数,不然选择dp[n-1]

2.1 递归算法

package xyz.cglzwz.jd.t2;

import java.util.Scanner;

public class Copy {
	static int[] dp;
	
	public static void main(String[] args) {
		// 输入部分
		Scanner in = new Scanner(System.in);
		int m = Integer.valueOf(in.nextLine());
		String[] Sm = new String[m];
		for (int i = 0; i < Sm.length; ++i) {
			Sm[i] = in.nextLine();
		}
		String T = in.nextLine();
		
		// 对输入的Sm串从小到大选择排序
		for (int i = 0; i < Sm.length; ++i) {
			int flag = i;
			for (int j = i + 1; j < Sm.length; ++j) {
				if (Sm[j].length() < Sm[flag].length())
					flag = j;
			}
			if (flag != i) {
				String temp = Sm[flag];
				Sm[flag] = Sm[i];
				Sm[i] = temp;
			}
		}
		
		// 定义数据
		int n = T.length();
		dp = new int[n+1];
		for (int i = 0; i < dp.length; ++i)
			dp[i] = 0;
		int ans = 0;
		
		// 调用递归
		ans = find(Sm, T, n);
		
		System.out.println(ans);
	}
	
	
	/**
	 * 递归法
	 * 
	 * @param Sm Sm子串集合
	 * @param T  
	 * @param n  
	 * @return
	 */
	static int find(String[] Sm, String T, int n) {
		// 出口
		if (n == 0)
			return 0;
		
		for (int i = 0; i < Sm.length && Sm[i].length() <= n; ++i) {
			int len = Sm[i].length();
			if (T.substring(n-len, n).equals(Sm[i])) {
				dp[n-len] = find(Sm, T, n-len);
				dp[n] = Math.max(dp[n-len] + 1, dp[n]);
			}
		}
		
		if (dp[n - 1] == 0)
			dp[n-1] = find(Sm, T, n - 1);
		return Math.max(dp[n], dp[n - 1]);
	}
}

比较简单,但是时间空间肯定不允许,case通过率不会超过10%;

2.2 递推法

package xyz.cglzwz.jd.t2;

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		// 输入部分
		Scanner in = new Scanner(System.in);
		int m = Integer.valueOf(in.nextLine());
		String[] Sm = new String[m];
		for (int i = 0; i < Sm.length; ++i) {
			Sm[i] = in.nextLine();
		}
		String T = in.nextLine();
		
		// 对输入的Sm串从小到大排序
		for (int i = 0; i < Sm.length; ++i) {
			int flag = i;
			for (int j = i + 1; j < Sm.length; ++j) {
				if (Sm[j].length() < Sm[flag].length())
					flag = j;
			}
			if (flag != i) {
				String temp = Sm[flag];
				Sm[flag] = Sm[i];
				Sm[i] = temp;
			}
		}
		
		// 定义数据
		int n = T.length();
		int[] dp = new int[n+1];
		for (int i = 0; i < dp.length; ++i)
			dp[i] = 0;
		int ans = 0;
		
		// 递推
		for (int k = 1; k <= n; ++k) {
			for (int i = 0; i < Sm.length && Sm[i].length() <= k; ++i) {
				int len = Sm[i].length();
				if (T.substring(k-len, k).equals(Sm[i])) {
					dp[k] = Math.max(dp[k-len] + 1, dp[k]);
				}
			}
			dp[k] = Math.max(dp[k], dp[k-1]);
		}
				
		ans = dp[n];
		System.out.println(ans);
	}	
}

这样就全部AC了,注意的是dp数组别定义为全局的,不然卡内存。

你可能感兴趣的:(京东,求T串中最多的不相交Sm子串的,算法程序设计)