D. Alyona and Strings
链接:
http://codeforces.com/contest/682/problem/D
题意:
给你两个长度分别为N和M的字符串,现在让你从两个字符串中挑出k个不重叠的子串,且这些子串在两个字符串中出现的次序一样,问你这k个子串的最长长度为多少。
题解:
F[i][j]表示第一个字符串的i位置和第二个字符串的j位置开始的最长前缀的长度,F[i][j] = F[i-1][j-1]+1 (a[i-1] == b[j-1]),又设dp[i][j][k] 表示现在匹配到第一个字符串中的i和第二个字符串中的j且之前已经匹配了k-1个子串的最长长度,那么dp[i][j][k] = max(dp[i-1][j][k],dp[i][j-1][k]),若F[i][j]存在则还有dp[i][j][k] = max(dp[i][j][k],dp[i-F[i][j]][j-F[i][j]][k-1] + F[i][j]).
代码:
#include<iostream> #include<string> #include<algorithm> using namespace std; const int maxn = 1000 + 10; int f[maxn][maxn]; int dp[maxn][maxn][11]; int main() { int n, m, k; cin >> n >> m >> k; string s, t; cin >> s >> t; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (s[i - 1] == t[j - 1]) f[i][j] = f[i - 1][j - 1] + 1; int ans = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) for (int l = 1; l <= k; l++) { dp[i][j][l] = max(dp[i - 1][j][l], dp[i][j - 1][l]); if (f[i][j]) dp[i][j][l] = max(dp[i][j][l], dp[i - f[i][j]][j - f[i][j]][l - 1] + f[i][j]); ans = max(ans, dp[i][j][l]); } cout << ans << endl; return 0; }