题目链接:点击打开链接
思路:
类似于LCS, 只需用d[i][j][k][p]表示当前到了s1[i]和s2[j], 形成了k个子序列, 当前是否和上一个字符和上一个字符相连形成一个序列的最长序列和。
细节参见代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include <cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const double eps = 1e-6; const double PI = acos(-1); const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; // & 0x7FFFFFFF const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 1000 + 10; int T,n,m, d[maxn][maxn][12][2], vis[maxn][maxn][12][2], kase = 0, k; inline bool vail(int i, int j) { if(i < n && j < m) return true; else return false; } char s1[maxn], s2[maxn]; int dp(int i, int j, int s, int p) { int& ans = d[i][j][s][p]; if(s > k) return -INF; if(i >= n || j >= m) { if(s == k) return 0; else return -INF; } if(vis[i][j][s][p] == kase) return ans; vis[i][j][s][p] = kase; ans = 0; if(p) { if(s1[i] == s2[j]) ans = max(ans, dp(i+1, j+1, s, p) + 1); if(s1[i] == s2[j]) ans = max(ans, dp(i+1, j+1, s+1, p) + 1); ans = max(ans, dp(i+1, j+1, s, p^1)); ans = max(ans, dp(i, j+1, s, p^1)); ans = max(ans, dp(i+1, j, s, p^1)); } else { if(s1[i] == s2[j]) ans = max(ans, dp(i+1, j+1, s+1, p^1) + 1); ans = max(ans, dp(i+1, j+1, s, p)); ans = max(ans, dp(i, j+1, s, p)); ans = max(ans, dp(i+1, j, s, p)); } return ans; } int main() { scanf("%d%d%d",&n,&m,&k); ++kase; scanf("%s%s", s1, s2); int ans = dp(0, 0, 0, 0); printf("%d\n", ans); return 0; }