Alyona and Strings CodeForces - 682D DP

Alyona and Strings CodeForces - 682D DP

题目大意:
给你两个长度均小于等于1000的字符串,你要在第一个串中找k(k<=10)个连续的子串,并且这些字串在第二个字符串中均出现且顺序相同,问这些字串最大的长度和。
题目分析:很显然,如果没有k个子串的限制的话,就是一个最大公共子序列的问题。现在就是K个最大公共子序列的问题了。
当时想的时候,是用的三维数组,多开了一维来表示k个,然后就发现当我判断要不要多加一个来隔开他们的时候,需要判断他们是不是连续的,然后就想不出来了。
dp[i][j][k][0]表示第一个字符取前i个,第二个字符取前j个,已经分配到了k段,这第k段还会继续延伸的最大长度和。
dp[i][j][k][1]表示第一个字符取前i个,第二个字符取前j个,已经分配到了k段,这第k段不会继续延伸的最大长度和。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e3 + 100;
int dp[maxn][maxn][20][2];
char str1[maxn], str2[maxn];

int main()
{
    int n, m, K;
    scanf("%d %d %d", &n, &m, &K);
    scanf("%s %s", str1 + 1, str2 + 1);
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            if(str1[i] == str2[j]) {
                for(int k = 1; k <= K; k++) {
                    dp[i][j][k][0] = max(dp[i - 1][j - 1][k][0], dp[i - 1][j - 1][k - 1][1]) + 1;
                    //dp[i - 1][j - 1][k][0]表示新来的i,j跟之前的在一起
                    //dp[i - 1][j - 1][k - 1][1]表示新来的i,j独立
               }
            }
            for(int k = 1; k <= K; k++) {
                dp[i][j][k][1] = max(max(dp[i - 1][j][k][1], dp[i][j - 1][k][1]), dp[i][j][k][0]);
                //dp[i][j][k][1] = dp[i][j][k][0] 是因为可以把想要继续延续下去的ij断开 
            }

        }
    }
    printf("%d\n", dp[n][m][K][1]);
}

猜你喜欢

转载自blog.csdn.net/deerly_/article/details/80962492