最简单的LIS;
设字符串为 a = acc b = cc
则dp数组为
0 0
1 1
1 2
b[0] = a[1], b[1] = a[1] 防止这里算两个
要清楚的是 怎么不重复计算 也就是dp[1]的计算
首先dp[1][0] = 1;
再处理 dp[1][1], 因为 b[1] = a[1], 它是可以加一的 加哪一个呢? 要是直接继承左边的 选择dp[1][0] + 1 就会发生重复计算 因为b[0] = a[1], dp[1][0]已经是加上了一个共同字符的值
解决方法是 选择 dp[0][0] + 1 也就是继承上一轮的dp值, 因为上一轮只搞了a[0], 没有倒腾a[1], 即使 b[0] = a[1]也没有算进去, 所以避免了重复, 以此类推
写成滚动数组
#include <stdio.h> #include <iostream> #include <cstring> #include <vector> #include <queue> #include <set> #include <sstream> #include <algorithm> const int si = 1e4; using namespace std; int dp[2][si]; int main() { string sss, a, b; while (getline(cin, sss)) { stringstream ss(sss); ss >> a; ss >> b; fill(dp[0], dp[0] + 2 * si, 0); int sa = a.size(), sb = b.size(); int e = 0; for (int i = 1; i <= sa; i++) { for (int j = 1; j <= sb; j++) { dp[e][j] = max(dp[1 - e][j], dp[e][j - 1]); if (b.at(j - 1) == a.at(i - 1)) { dp[e][j] = max(dp[1 - e][j - 1] + 1, dp[e][j]); //dp[1 - e][j - 1]是j-1在上一层没有匹配第i-1个的 所以不会重复计算 } } e = 1 - e; } cout << dp[1 - e][sb] << endl; } return 0; }