• 【Luogu】P3311数数(AC自动机上DP)


      题目链接

      蒟蒻今天终于学会了AC自动机,感觉很稳

      (后一句愚人节快乐)

      这题开一个f[i][j][k]表示有没有受到限制,正在枚举第j位,来到了AC自动机的第k个节点

      的方案数

      随后可以刷表更新

      注意如果是在枚举第一位的话注意前导0

      

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #define maxl 2000
    #define maxu 10
    #define mod 1000000007
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    inline int count(int i){    return i-'0';    }
    
    int tree[maxl*maxu][maxu];
    int fail[maxl*maxu];
    int val[maxl*maxu];
    int tot;
    char c[maxl];
    char s[maxl];
    long long f[3][maxl][maxl];
    bool vis[maxl];
    
    
    void update(){
        int n=strlen(c+1);    int now=0;
        for(int i=1;i<=n;++i){
            if(tree[now][count(c[i])]==0)    tree[now][count(c[i])]=++tot;
            now=tree[now][count(c[i])];
        }
        val[now]++;
        return;
    }
    
    void makefail(){
        queue<int>q;
        for(int i=0;i<10;++i)
            if(tree[0][i])    q.push(tree[0][i]);
        while(!q.empty()){
            int from=q.front();q.pop();
            for(int i=0;i<10;++i){
                if(tree[from][i]==0){
                    tree[from][i]=tree[fail[from]][i];
                    continue;
                }
                fail[tree[from][i]]=tree[fail[from]][i];
                val[tree[from][i]]|=val[tree[fail[from]][i]];
                q.push(tree[from][i]);
            }
        }
        return;
    }
    
    inline void add(long long &a,int b){
        a=(a+b)%mod;
    }
    
    int main(){
        scanf("%s",s+1);int n=strlen(s+1);
        int m=read();
        for(int i=1;i<=m;++i){
            scanf("%s",c+1);
            update();
        }
        long long ans=0;
        makefail();
        for(int i=0;i<n;++i)
            for(int j=0;j<=tot;++j){
                if(f[0][i][j]){
                    int now=s[i+1]-'0';
                    for(int k=0;k<now;++k){
                        int nxt=tree[j][k];
                        if(val[nxt]==0)    add(f[1][i+1][nxt],f[0][i][j]);
                    }
                    int nxt=tree[j][now];
                    if(val[nxt]==0)    add(f[0][i+1][nxt],f[0][i][j]);
                }
                if(f[1][i][j]){
                    for(int k=0;k<10;++k){
                        int nxt=tree[j][k];
                        if(val[nxt]==0)    add(f[1][i+1][nxt],f[1][i][j]);
                    }
                }
                if(j==0){
                    if(i==0){
                        int now=s[i+1]-'0';
                        for(int k=1;k<now;++k){
                            int nxt=tree[j][k];
                            if(val[nxt]==0)    add(f[1][i+1][nxt],1);
                        }
                        int nxt=tree[j][now];
                        if(val[nxt]==0)    add(f[0][i+1][nxt],1);
                    }
                    else{
                        for(int k=1;k<10;++k){
                            int nxt=tree[j][k];
                            if(val[nxt]==0)    add(f[1][i+1][nxt],1);
                        }
                    }
                }
            }
        for(int i=0;i<=tot;++i){
            add(ans,f[0][n][i]);
            add(ans,f[1][n][i]);
        }
        ans=(ans+mod)%mod;
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    概率论基础学习笔记
    树点涂色
    2016北京集训测试赛(八)Problem C: 直径
    BZOJ 4361 ISN
    2017省选集训测试赛(二十五)Problem B recollection
    2016北京集训测试赛(六)Problem B: 矩阵
    记录Vue和Jquery混合开发中关于点击事件的一个bug
    记录JQ-WEUI中滚动加载的一个BUG
    Vue Elementui 如何让输入框每次自动聚焦
    什么是CDN加速?(转载)
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8687922.html
Copyright © 2020-2023  润新知