版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenbetter1996/article/details/89289724
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数组别定义为全局的,不然卡内存。