zoukankan      html  css  js  c++  java
  • [CF1426F] Number of Subsequences

    Description

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

    Solution

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

    (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;
        
    }
    
  • 相关阅读:
    【计算机网络】复习集(更新中)
    滑雪 (记忆化搜索)
    橱窗布置
    复制书稿 (dp+贪心)
    8786:方格取数 (多线程dp)
    编辑距离
    8782:乘积最大
    合并石子 (区间dp+前缀和)
    6045:开餐馆
    6049:买书 (完全背包)
  • 原文地址:https://www.cnblogs.com/mollnn/p/14048640.html
Copyright © 2011-2022 走看看