Codeforces1084 C. The Fair Nut and String(dp)

题意:

给定字符串S,问该串中有多少个子序列aaa…,满足相邻a之间在原序列中至少存在一个b。

数据范围:|S|<=1e5

解法:
把除了a和b的其他字符删掉,

当s[i]='a',
令d[i]表示当前方案数,
转移:
1.当前选,且接在其他序列后面,方案数为sum(d[k]),其中[k+1,i-1]中出现过'b'
2.当前选,但是单独作为一个序列,方案数为1
2.当前不选,那么方案数为d[i-1],

如果判断有多少个满足条件的k,[k+1,i]中出现过'b'?
可以用一个变量last记录,当遇到'b'的时候,令last=d[i],
那么当遇到a的时候,d[i]=d[i-1]+last+1,

dp数组可以优化掉,用变量ans存当前d[i]就行了:
1.遇到'b',last=ans.
2.遇到'a',ans=ans+last+1.
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PI pair<int,int>
const int maxm=1e5+5;
const int mod=1e9+7;
char s[maxm];
int n;
signed main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    int last=0;
    int ans=0;
    for(int i=1;i<=n;i++){
        if(s[i]=='b'){
            last=ans;
        }else if(s[i]=='a'){
            ans=(ans+last+1)%mod;
        }
    }
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值