CF 682D
- 真是蠢了好久…
- @ 题意:最长公共子串,并且这个匹配对于s和t来说都是分割成k块子串(不能再多了),
- 幸好k小的一比(k < 10),。
- @ dp[k][i][j][st == 0 or 1]表示s的前i个字符与t前j个字符在k划分下st == 1为连续,
- 否则不连续的最大匹配个数。
- st1的转移方式是显然只有当前 s[i] == t[j]时候才能转移,能转移过来的状态有很多,
- 一定要想清楚再写,不然Debug到死。
#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <algorithm>const int maxn = 1107;int n, m, z;std::string s, t;int dp[2][maxn][maxn][2];void debug(int now, int st){ std::cout << " "; for(int i = 0; i < m; i ++) { std::cout << t[i] << ' '; } std::cout << "\n" <<n << m << "\n"; for(int i = 1; i <= n; i ++){ for(int j = 1; j <= m; j ++){ if(j == 1) std::cout << s[i - 1] << " : "; std::cout << dp[now][i][j][st] << ' '; } std::cout << "\n"; } std::cout << std::endl;}int main(){ std::cin >> n >> m >> z; std::cin >> s; std::cin >> t; int now = 0, pre = 0, ans = 0; for(int k = 1; k <= z; k ++){ now = pre ^ 1; memset(dp[now], 0, sizeof(dp[now])); for(int i = k; i <= n; i ++){ for(int j = k; j <= m; j ++){ dp[now][i][j][0] = std::max(dp[now][i - 1][j][0], dp[now][i][j - 1][0]); if(s[i - 1] == t[j - 1]){ dp[now][i][j][1] = std::max(std::max(dp[pre][i - 1][j - 1][0], dp[pre][i - 1][j - 1][1]), dp[now][i - 1][j - 1][1]) + 1; dp[now][i][j][0] = std::max(dp[now][i][j][0], std::max(dp[pre][i - 1][j - 1][0], dp[pre][i - 1][j - 1][1]) + 1); } dp[now][i][j][0] = std::max(dp[now][i][j][0], dp[now][i][j][1]); ans = std::max(ans, std::max(dp[now][i][j][0], dp[now][i][j][1])); } } pre = now; } std::cout << ans << "\n";}