版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
写在前面
- 思路分析
- 给出m中颜色作为喜欢色(给出顺序),然后给出1串长度为L的颜色序列,现在要去掉这个序列中不喜欢的颜色,然后求剩下序列的1个子序列,使得这个子序列表示的颜色顺序符合自己喜欢的颜色顺序,不1定所有喜欢颜色都出现。
- 分析:
- 喜欢颜色是不重复,把喜欢颜色的序列依次存储到数组中, book[i] = j表示i颜色的下标为j。
- 先在输入的时候剔除不在喜欢的序列中的元素,然后把剩余的保存在数组a中。
- 按照最长不下降⼦子列列方式,对于从前到后的每1个i,如果它前面所有的j,1下子找到1个j的下标book[j]比book[i]小,此时就更新dp[i]使它 = max(dp[i], dp[j] + 1);
- 同时再每1次遍历完成1次j后更新maxn的值为长度最大值,最后输出maxn
- 新知识点,学习ing
测试用例
-
input: 6 5 2 3 1 5 6 12 2 2 4 1 5 5 6 3 1 1 5 6 output: 7
ac代码
- 过程详情
- 把输入的喜欢颜色顺序转化成递增顺序排序的1,2,3……N,也就是用一个整数数组a[i]表示颜色标号i的先后顺序。
- 题目中的2 3 1 5 6 就可以变成 a[2] = 1,a[3] = 2, a[1] = 3,a[5] = 4, a[6] = 5
- 然后将下面L中颜色转化成喜欢颜色的顺序。用一个vector存储。
- 题目中的2 2 4 1 5 5 6 3 1 1 5 6变成了颜色序列对应的1 1 0 3 4 4 5 2 3 3 4 5
- 对于a[i] == 0的颜色,说明这个颜色并非Eva喜欢的颜色。所以不用存储到vector中。
- vector实际存储的值为1 1 3 4 4 5 2 3 3 4 5
- 最后按照最长上升子序列对vector中的颜色顺序进行处理
-
#include <iostream> #include <vector> using namespace std; int book[201], a[10001], dp[10001]; int main() { int n, m, x, l, num = 0, maxn = 0; scanf("%d %d", &n, &m); for(int i = 1; i <= m; i++) { scanf("%d", &x); book[x] = i; } scanf("%d", &l); for(int i = 0; i < l; i++) { scanf("%d", &x); if(book[x] >= 1) a[num++] = book[x]; } for(int i=0; i<num; i++) { dp[i] = 1; for(int j=0; j<i; j++) if(a[i]>=a[j]) dp[i] = max(dp[i],dp[j]+1); maxn = max(dp[i], maxn); } printf("%d", maxn); return 0; }
知识点小结
- 最长不下降子序列LIS(
Longest increasing subsequence
) - 最长公共子序列LCS(
Longest common subsequence
)- 公共子串 VS 公共子序列
- 公共子串: 指连续的公有字符串
- 公共子序列: 指两个字符串都任意删除0个或多个字符后得到的公有字符串,子序列可以是不连续的
- 状态转移方程
- 公共子串 VS 公共子序列