Codeforces Round #358 (Div. 2) D. Alyona and Strings DP

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;
}

 

posted @ 2016-09-27 13:57  Flowersea  阅读(183)  评论(0编辑  收藏  举报