状态:$f(i,j)$为序列$a[i]$和序列$b[j]$(一定包含结尾)的最长LCIS
转移:显然只有当$a_i=b_j$才会转移。
$f(i,j)=\max(f(x,y))+1\\
x\in[1,i],y\in [1,j],a[x] < a[i],b[y] < b[j]$
由于$f(i,j)$保证了只有$a[i]=b[j]$才有值,所以限制条件可以简化为:
$x\in[1,i],y\in [1,j],b[y] < b[j]$($a[x]=b[y],a[i]=b[j]$)
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= n; ++ j)
if(a[i] == b[j])
for(int x = 1; x <= i; ++ x)
for(int y = 1; y = j; ++ y)
if(a[x] < a[i])
if(f[i][j] < f[x][y]+1)
f[i][j] = f[x][y] + 1;
注意到当$i,j$均不会变小的时候,$(x,y)$这个集合只会越来越大,所以我们开一个变量记录$f(x,y)$的最大值就好了,然后每次$i+1$了$j$要从$1$开始,要重新算最大值,但是显然这个时候最大值是0,然后后面把$j$变大的过程只需要维护这个最大值就好了。
for(int i = 1; i <= n; ++ i)
{
int maxv = 0;
for(int j = 1; j <= n; ++ j)
{
for(int x = 1; x < i; ++ x)
if(a[x] < a[i])
if(maxv < f[x][j])
maxv = f[x][j];
if(a[i] == b[j])
f[i][j] = maxv + 1;
}
}
再看,我们可以省去状态的第一维,因为我们使用状态的第一维的时候,当第二维固定了以后,我们其实只是在其中找了个最大值出来,所以可以写成这样:
for(int i = 1; i <= n; ++ i)
{
int maxv = 0;
for(int j = 1; j <= n; ++ j)
{
if(b[j] < a[i])
if(maxv < f[j])
maxv = f[j];
if(a[i] == b[j])
f[j] = maxv + 1;
}
}
最后我们找出$f$中最大值就好了
u1s1, 这版本思路不错
怎么想到的,厉害