2021中国大学生程序设计竞赛(CCPC)- 网络选拔赛(重赛)hdu-7131

题目大意:

给定一个序列s,求【前缀是nunhehheh后缀是>=1个a】的子序列个数

题目思路:

定义dp[i][j]为s序列前i个字符与nunhehheh匹配j个字符的个数

预处理出每个i后边有多少个a,用数组suf表示

对于每个dp[i][8]成2的suf[i]幂次方

重点解释一下为什么是dp[i][8]而不是dp[i][9]

    --因为前缀是以h结尾,每次匹配到h时我们对答案加上dp[i][8]*2^suf[i]
    
    --如果是dp[i][9]的话,会重复加上之前我们计算过的

代码:

LL P[N], dp[N][20], suf[N];
char s[N], p[11] = "@nunhehheh";

inline void solve()
{
    char ch = getchar();
    scanf("%s", s + 1);
    memset(dp, 0, sizeof dp);
    memset(suf, 0, sizeof suf);
    int len = strlen(s + 1);
    for (int i = len; i >= 0; i -- )
    {
        dp[i][0] = 1;
        suf[i] = (suf[i + 1] + (s[i] == 'a')) % mod;
    }

    for (int i = 1; i <= len; i ++ )
    {
        for (int j = 1; j <= 8; j ++ )
        {
            if (s[i] == p[j]) dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
            else dp[i][j] = dp[i - 1][j];
        }
    }
    LL ans = 0;
    for (int i = 9; i <= len; i ++ )
    {
        if (s[i] == 'h')
        {
            ans += dp[i][8] * (P[suf[i]] - 1) % mod;
            ans %= mod;
        }
    }
    printf("%lld\n", ans);
}
int main()
{

    int T; scanf("%d", &T);

    P[0] = 1;
    for (int i = 1; i <= N; i ++ )
        P[i] = P[i - 1] * 2 % mod;
    
    while (T -- )
    {
         solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值