NOIP2015 子串 解题报告(DP)

来源:互联网 发布:淘宝销售方案 编辑:程序博客网 时间:2024/06/05 18:21

在线评测:

http://codevs.cn/problem/4560/

整体思路:

dp i,j,k,(0/1) 表示A扫到第i位,B扫到第j位,还可以分成k个子串,当前 这一位加不加入子串;

这时候我们发现空间是不足以AC的,所以我们可以滚动数组一下。

最后我们可以得到DP方程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for (int i = 1;i <= n;i++)
    {
        for (int j = m;j >= 1;j--)
        {
            for (int o = k;o >= 0;o--)
            {
                f[j][o][0] = f[j][o][0] +f[j][o][1];
                f[j][o][0] %= mo;
                if (a[i-1] != b[j-1])
                    f[j][o][1] = 0;else
                    if (o > 0)
                    f[j][o][1] = f[j-1][o-1][0] + f[j-1][o-1][1] + f[j-1][o][1];
                f[j][o][1] %= mo;
            }
        }
    }

失误之处:

开始没有取模,,取模后发现取模的值都爆int,然后gg,就60分

体会心得:

看好数据的范围,,,

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k;
const long long mo = 1000000007;
long long f[250][250][2];
char a[1200],b[1200];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    scanf("%s%s",a,b);
    f[0][0][0] = 1;
    for (int i = 1;i <= n;i++)
    {
        for (int j = m;j >= 1;j--)
        {
            for (int o = k;o >= 0;o--)
            {
                f[j][o][0] = f[j][o][0] +f[j][o][1];
                f[j][o][0] %= mo;
                if (a[i-1] != b[j-1])
                    f[j][o][1] = 0;else
                    if (o > 0)
                    f[j][o][1] = f[j-1][o-1][0] + f[j-1][o-1][1] + f[j-1][o][1];
                f[j][o][1] %= mo;
            }
        }
    }
    printf("%lld\n",(f[m][k][0] + f[m][k][1]) % mo);
    return 0;
}

0 0
原创粉丝点击