我感觉这是大部分人不理解优化写法的地方(包括我在内)
大概思路就是下面说的,在下表达能力不够强,不理解的可以多看几遍,也可以留言,尽量帮大家解决
for(int i = 1; i <= n; i ++) cin >> b[i];
int maxv;
for(int i = 1; i <= n; i ++)
{
maxv = 1;
for(int j = 1; j <= n; j ++)
{
f[i][j] = f[i - 1][j];
// if(a[i] == b[j])
// {
// f[i][j] = max(f[i][j], 1);
// for(int k = 1; k < j; k ++)
// {
// if(b[j] > b[k]) f[i][j] = max(f[i][j], f[i - 1][k] + 1);
// }
// }
// 等效替代的原理(特别注意maxv在更新的时候就已经加一了,也就是下一行式子的意义)
//if(b[j] > b[k]) f[i][j] = max(f[i][j], f[i - 1][k] + 1);
// 仔细观察朴素写法,我们只有在a[i] == b[j]时才去按照从小到大的顺序枚举公共上升子序列的倒数第二个数时谁
// 但是这样做其实重复了好多次, 只要a[i] == b[x], (x就是b序列和a[i]相等的项的下标), 我们就去枚举,那我们可以
// 用一个变量维护这样的过程, 这里特别重要的一点是maxv求的是 a[i] == b[x],且b[x] 是 要求的序列的倒数第二项,那么
// 下面我们更新maxv的时候其实就体现了这一点,这样当 我又遍历到a[i] == b[j]的时候直接比较 f[i - 1][j] 和 maxv的
// 大小就可以了.
if(a[i] == b[j])
{
f[i][j] = max(maxv, f[i][j]);// 所以这里我们可以直接使用
}
if(a[i] > b[j]) maxv = max(maxv, f[i - 1][j] + 1); // 只要此时的 b[j] < a[i]也就是说它可以体现上升的过程
//那么他就可以用来更新maxv, 特别注意f[i - 1[j] 要
// 加1,也就是默许了此时j的相当于序列的倒数第二项
}
}
倒数第二行
f[i - 1[j]
少了个括号呜呜写的很好 理解了呜呜 谢谢佬
hh