题意:
给一个长度为n的由a,b,c,?组成的字符串,?代表任意填abc,问所有情况产生的字符串中有多少个abc子序列。
思路:
经典递推dp,特殊的地方在于?的处理上,当?取a的时候应该加的值不是1,设当前下标前出现过的?次数为x,当前位置出现a的时候加的值是3^x,再把?取bc的情况传递一下就ok了
#include<bits/stdc++.h>
#define LL long long
#define INF INT64_MAX
#define MOD 1000000007
#define ls rt << 1
#define rs rt << 1 | 1
using namespace std;
typedef pair<int,int>pa;
const int N = 3e5+7;
LL dp[N][4];
char s[N];
int main(){
int n, m, k;
scanf("%d%s", &n, s+1);
LL cnt = 1ll;
for(int i = 1;i <= n;i++){
if(s[i]=='?'){
dp[i][1] = (dp[i-1][1]+cnt)%MOD;
dp[i][2] = dp[i-1][2];
dp[i][3] = dp[i-1][3];
dp[i][1] = (dp[i][1] + dp[i-1][1])%MOD;
dp[i][2] = (dp[i][2] + dp[i-1][1] + dp[i-1][2])%MOD;
dp[i][3] = (dp[i][3] + dp[i-1][3])%MOD;
dp[i][1] = (dp[i][1] + dp[i-1][1])%MOD;
dp[i][2] = (dp[i][2] + dp[i-1][2])%MOD;
dp[i][3] = (dp[i][3] + dp[i-1][2] + dp[i-1][3])%MOD;
cnt = cnt*3%MOD;
}
else if(s[i]=='a'){
dp[i][1] = (dp[i-1][1]+cnt)%MOD;
dp[i][2] = dp[i-1][2];
dp[i][3] = dp[i-1][3];
}
else if(s[i]=='b'){
dp[i][1] = (dp[i][1] + dp[i-1][1])%MOD;
dp[i][2] = (dp[i][2] + dp[i-1][1] + dp[i-1][2])%MOD;
dp[i][3] = (dp[i][3] + dp[i-1][3])%MOD;
}
else if(s[i]=='c'){
dp[i][1] = (dp[i][1] + dp[i-1][1])%MOD;
dp[i][2] = (dp[i][2] + dp[i-1][2])%MOD;
dp[i][3] = (dp[i][3] + dp[i-1][2] + dp[i-1][3])%MOD;
}
//printf("%lld, %lld, %lld\n", dp[i][1], dp[i][2], dp[i][3]);
}
printf("%lld\n", dp[n][3]);
return 0;
}