AGC22E_Median Replace(自动机)

个人博客上的题解

题目传送门
题目大意:给你一个由’0’,’1’,’?’组成的串,’?’可以为’0’or’1’,每次操作你可以在原串中选连续的三个数使他们合并为他们的中位数
如’010’可以变成’0’,求有多少种方案(关于’?’的取值)使得原串是能在若干次操作后变为’1’(即beautiful的)

我们可以发现如果对所有可能的01串构建自动机,那么这个自动机的状态是有限的,然后我们就可以在自动机上DP求方案数啦
具体构建方法可以看下图和代码(不要嫌弃我画的图丑QAQ……
蓝色是0边,红色是1边,红色节点是beautiful的节点
自动机
刚开始看错题了,把中位数看成了中间的数卡了好久……英语差……

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int P=1e9+7;
char st[300005];
int f[300005][8],ch[8][2]; //f[i][j]表示匹配到字符串中第i个字符自动机上第j个节点的方案数,ch[i][j]表示自动机上第i个节点接受j后到达的节点
void build()
{
    ch[0][0]=2; ch[0][1]=1; //0节点为空串
    ch[1][0]=3; ch[1][1]=5; //1节点为1
    ch[2][0]=4; ch[2][1]=7; //2节点为0
    ch[3][0]=6; ch[3][1]=1; //3节点为10
    ch[4][0]=2; ch[4][1]=2; //4节点为00
    ch[5][0]=5; ch[5][1]=5; //5节点为11
    ch[6][0]=3; ch[6][1]=3; //6节点为100
    ch[7][0]=2; ch[7][1]=1; //7节点为01
}
int main()
{
    build();
    scanf("%s",st+1);
    int n=strlen(st+1);
    f[n][1]=f[n][5]=1; //节点1和5是一定beautiful的
    for (int i=n-1; i>=0; i--)
        for (int j=0; j<=7; j++)
        {
            if (st[i+1]!='1') f[i][j]+=f[i+1][ch[j][0]];
            if (st[i+1]!='0') f[i][j]+=f[i+1][ch[j][1]];
            if (f[i][j]>=P) f[i][j]-=P;
        }
    printf("%d\n",f[0][0]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值