LCIS
状态:
d p i , j dp_{i, j} dpi,j表示 a 1 ∼ i a_{1\sim i} a1∼i和 b 1 ∼ j b_{1\sim j} b1∼j中以 b j b_j bj结尾的公共上升子序列的集合,值表示该集合中所有公共上升子序列的长度的最大值
状态转移方程:
d
p
i
,
j
=
{
d
p
i
−
1
,
j
(
a
i
≠
b
j
)
max
1
≤
k
<
j
,
b
k
<
b
j
d
p
i
−
1
,
k
(
a
i
=
b
j
)
\displaystyle dp_{i,j}=\left\{\begin{matrix} dp_{i-1,j} (a_i\ne b_j) \\ \max_{1\le k<j,b_k<b_j}dp_{i - 1,k}(a_i=b_j) \end{matrix}\right.
dpi,j={dpi−1,j(ai=bj)max1≤k<j,bk<bjdpi−1,k(ai=bj)
时间复杂度:
O
(
n
3
)
O(n^3)
O(n3)
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
{
if (a[i] != b[j])
{
dp[i][j] = dp[i - 1][j];
continue;
}
// 这个位置要从k = 0开始, 因为这个情况有前面没有构成的情况,不能省略
for (int k = 0; k < j; ++k)
if (b[k] < b[j])
dp[i][j] = max(dp[i][j], dp[i - 1][k] + 1);
}
}
我们可以改一改
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
{
if (a[i] != b[j])
{
dp[i][j] = dp[i - 1][j];
continue;
}
int maxx = 0; // 初始前面没有数
for (int k = 1; k < j; ++k)
if (b[k] < b[j]) maxx = max(maxx, dp[i - 1][k]);
dp[i][j] = maxx + 1;
}
}
这样就可以改成 O ( n 2 ) O(n^2) O(n2)
for (int i = 1; i <= n; ++i)
{
int maxx = 0; // 初始前面没有数
for (int j = 1; j <= m; ++j)
{
if (a[i] != b[j]) dp[i][j] = max(dp[i][j], dp[i - 1][j]);
else dp[i][j] = max(dp[i][j], maxx + 1);
if (b[j] < a[i]) maxx = max(maxx, dp[i - 1][j]);
}
}
int ans = 0;
for (int i = 1; i <= m; ++i)
ans = max(ans, dp[n][i]);
printf("%d", ans);
改成一位数组
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
if (a[i] > b[j]) maxx = max(maxx, dp[j]);
if (a[i] == b[j]) dp[j] = maxx + 1;
}
}
int ans = 0;
for (int i = 1; i <= m; ++i)
ans = max(ans, dp[i]);
printf("%d", ans);