[NOIp2015]子串

Description

Luogu2679
\(A\)中选出\(k\)个非空子串且连起来是\(B\)的方案数。

Solution

这个题可以仿照最长公共子序列来定义状态\(f_{i,j,k}\)表示\(A\)串的前\(i\)个和\(B\)串的前\(j\)个匹配,且用了\(k\)个子串,并且必须选\(A_i\)。但是这样并不是很好转移。
所以我们添加一个辅助状态\(s_{i,j,k}\)表示\(A\)串的前\(i\)个和\(B\)串的前\(j\)个匹配,且用了\(k\)个子串,但是不一定选\(A_i\)。于是就有如下几种转移:

\(A_i = B_j\),则\(f_{i,j,k} = f_{i-1,j-1,k} + s[i-1][j-1][k-1]\)(分别对应\(A_i\)\(A_{i-1}\)组合成一个子串或者是单独成一个子串),否则\(f_{i,j,k} = 0\)
而无论如何,\(s_{i,j,k} = f_{i, j, k} + s_{i-1,j,k}\)

Code

#include <cstdio>

typedef long long ll;
const int N = 1010;
const int M = 210;
const ll MOD = 1e9 + 7;

ll f[M][M][2];
char a[N], b[M];
int n, m, k;

int main() {
    scanf("%d%d%d", &n, &m, &k);
    scanf("%s", a+1); scanf("%s", b+1);
    f[0][0][0] = f[0][0][1] = 1;
    for (int i = 1; i <= n; ++i)
        for (int j = m; j; --j)
            for (int K = k; K; --K) {
                if (a[i] == b[j])
                    f[j][K][0] = (f[j-1][K][0] + f[j-1][K-1][1]) % MOD;
                else f[j][K][0] = 0;
                
                f[j][K][1] = (f[j][k][1] + f[j][K][0]) % MOD;
            }
    printf("%lld\n", f[m][k][1] % MOD);
}

Note

这个题我一开始提交的时候写的是%I64d错了一次,后来又因为忘记取模错了一次。这些小问题还是要仔细。

转载于:https://www.cnblogs.com/wyxwyx/p/noip201522.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值