题解 [牛客练习赛60C] 操作集锦

操作集锦

https://ac.nowcoder.com/acm/contest/4853/C

题目描述

给定一个长度为 的有小写字母组成的字符串。

求长度为 的本质不同的子序列个数,对 取模。

正解

如果设 为考虑到第 个位置,且第 个位置必须选,选出的本质不同的子序列个数。

设出状态不难,难的是转移如何不会重复。

如果一个子序列只在出现的第一次被算入答案,就不会计算重复了对吧。

考虑构造出序列自动机(位置为 ,字符 的下一个位置),这是找子序列第一次出现的常见套路。

那么转移就很简单了,当前位置为 ,枚举当前长度为 ,转移字符为 ,则有 的转移。

最后所有 就是答案了。

#include <bits/stdc++.h>
#define N 1005

using namespace std;

const int mod = 1e9 + 7;

int n, K;
int nex[N][26], f[N][N];
char s[N];

int main() {
    scanf("%d %d", &n, &K);
    scanf("%s", s + 1);
    for(int c = 0; c < 26; ++c)
        nex[n][c] = n + 1;
    for(int c = 0; c < 26; ++c)
        for(int i = n - 1; i >= 0; --i)
            nex[i][c] = (s[i + 1] == 'a' + c ? i + 1 : nex[i + 1][c]); 
    f[0][0] = 1;
    for(int i = 0; i < n; ++i)
        for(int j = 0; j <= n; ++j) {
            if(!f[i][j]) continue;
            for(int c = 0; c < 26; ++c)
                if(nex[i][c] <= n)
                    (f[nex[i][c]][j + 1] += f[i][j]) %= mod;
        }
    int ans = 0;
    for(int i = 0; i <= n; ++i)
        (ans += f[i][K]) %= mod;
    printf("%d\n", ans);
    return 0;
}
全部评论
请问这个题 暴力dfs为什么会超时
点赞 回复 分享
发布于 2020-03-28 16:31

相关推荐

点赞 评论 收藏
分享
小鹏、大疆、米哈游、MinMax小鹏上午投的下午就约面,进度未免也太快了
蛇年行大运fff:哥们 盗贴有意思吗,我发xhs上的给你搬过来了😅😅😅
点赞 评论 收藏
分享
苍蓝星上艾露:这简历。。。可以试试我写的开源简历优化工具https://github.com/weicanie/prisma-ai
点赞 评论 收藏
分享
评论
4
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务