关闭

NOIP2015 子串 解题报告(DP)

标签: NOIP2015dp
290人阅读 评论(0) 收藏 举报
分类:

在线评测:

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

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:15998次
    • 积分:793
    • 等级:
    • 排名:千里之外
    • 原创:65篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条