统计元音字母序列的数目【经典动态规划】

题目是P1220统计元音字母序列的数目
在这里插入图片描述
通过分析我们可以得知:

a前面只能接e、i、u
e前面只能接a或i
i前面只能接e、o
o前面只能接i
u前面只能接o、i

我们用dp[i]表示长度为i的字符串的个数,其中dp[i][j]表示dp[i]的5种状态,0≤j≤4。分别是以5个元音字母结尾的字符串。因此最终答案就是 d p [ n ] [ 0 ] + d p [ n ] [ 1 ] + d p [ n ] [ 2 ] + d p [ n ] [ 3 ] + d p [ n ] [ 4 ] dp[n][0]+dp[n][1]+dp[n][2]+dp[n][3]+dp[n][4] dp[n][0]+dp[n][1]+dp[n][2]+dp[n][3]+dp[n][4]
并且我们可以通过分析得知条件转移方程为:

d p [ n ] [ 0 ] = d p [ n − 1 ] [ 1 ] + d p [ n − 1 ] [ 2 ] + d p [ n − 1 ] [ 4 ] dp[n][0]=dp[n-1][1]+dp[n-1][2]+dp[n-1][4] dp[n][0]=dp[n1][1]+dp[n1][2]+dp[n1][4]
d p [ n ] [ 1 ] = d p [ n − 1 ] [ 0 ] + d p [ n − 1 ] [ 2 ] dp[n][1]=dp[n-1][0]+dp[n-1][2] dp[n][1]=dp[n1][0]+dp[n1][2]
d p [ n ] [ 2 ] = d p [ n − 1 ] [ 1 ] + d p [ n − 1 ] [ 3 ] dp[n][2]=dp[n-1][1]+dp[n-1][3] dp[n][2]=dp[n1][1]+dp[n1][3]
d p [ n ] [ 3 ] = d p [ n − 1 ] [ 2 ] dp[n][3]=dp[n-1][2] dp[n][3]=dp[n1][2]
d p [ n ] [ 4 ] = d p [ n − 1 ] [ 2 ] + d p [ n − 1 ] [ 3 ] dp[n][4]=dp[n-1][2]+dp[n-1][3] dp[n][4]=dp[n1][2]+dp[n1][3]

因为我们只需要储存前一个状态的信息,因此我们可以使用滚动数组优化,代码如下:

int countVowelPermutation(int n) {
    long long mod = 1e9 + 7;
    vector<long long> dp(5, 1);
    vector<long long> ndp(5);
    for (int i = 2; i <= n; ++i) {
        /* a前面可以为e,u,i */
        ndp[0] = (dp[1] + dp[2] + dp[4]) % mod;
        /* e前面可以为a,i */
        ndp[1] = (dp[0] + dp[2]) % mod;
        /* i前面可以为e,o */
        ndp[2] = (dp[1] + dp[3]) % mod;
        /* o前面可以为i */
        ndp[3] = dp[2];
        /* u前面可以为i,o */
        ndp[4] = (dp[2] + dp[3]) % mod;
        dp = ndp;
    }
    return (dp[0]+dp[1]+dp[2]+dp[3]+dp[4])%mod;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值