Description

给定一个串,包含字符 a,b,c,?,其中 ? 代表通配符,即这个位置可以是任意一个字符。求所有能与这个串匹配的确定串中,子序列 abc 的数量之和。

Solution

\(f[i][j]\) 表示对于 \(s[1..i]\),包含子序列 a,ab,abc 的数量之和各为多少,则对于 \(s[i] \neq ?\),有

\(f[i][1] = f[i-1][1] + (s[i]==a) \cdot 3^{cnt}, f[i][2] = f[i-1][1] + (s[i]==b) \cdot f[i-1][1], f[i][3] = f[i-1][3] + (s[i]==c) \cdot f[i-1][2]\)

对于 \(s[i] = ?\),则

\(f[i][1] = 3f[i-1][1] + 3^{cnt}, f[i][2] = 3f[i-1][1] + f[i-1][1], f[i][3] = 3f[i-1][3] + f[i-1][2]\)

#include <bits/stdc++.h>
using namespace std;

#define int long long 
const int N = 1e6 + 5;
const int mod = 1e9 + 7;

int qpow(int p,int q)
{
    return (q&1 ? p:1) * (q?qpow(p*p%mod,q/2):1) % mod;
}

int n;
string s;
int f[N][4];

signed main()
{
    ios::sync_with_stdio(false);

    cin>>n;
    cin>>s;

    int cnt=0;

    for(int i=1;i<=n;i++)
    {
        char c=s[i-1];

        if(c=='?')
        {
            f[i][1]=3*f[i-1][1]+qpow(3,cnt);
            f[i][2]=3*f[i-1][2]+f[i-1][1];
            f[i][3]=3*f[i-1][3]+f[i-1][2];
        }
        else 
        {
            f[i][1]=f[i-1][1]+(c=='a')*qpow(3,cnt);
            f[i][2]=f[i-1][2]+(c=='b')*f[i-1][1];
            f[i][3]=f[i-1][3]+(c=='c')*f[i-1][2];
        }

        for(int j=1;j<=3;j++) f[i][j]%=mod;

        if(c=='?') ++cnt;
    }

    cout<<f[n][3]<<endl;
    
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-02-25
  • 2021-11-07
  • 2022-12-23
  • 2022-12-23
  • 2022-02-06
  • 2022-12-23
猜你喜欢
  • 2022-02-19
  • 2021-05-16
  • 2021-05-27
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案