zoukankan      html  css  js  c++  java
  • ZOJ 3494 (AC自动机+数位DP)

    题意:给n个01字符串,求区间[x , y]中有多少个数写成BCD码后不包含以上01串。

    分析:先用01字符串建立AC自动机(注意标记危险结点),然后DP。dp[i][s]表示扫描前i位后有多少个数会到达自动机的结点s.

    注意:

    1.前导0的问题:不能转化成二进制在数位dp(否则处理不了前导0),安十进制进行数位dp!

    2.d[u][sub][zero]的sub是从n->0,不是从0->n(sub表示还剩几位)    Orz。。。

    //#pragma comment(linker, "/STACK:102400000")
    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<stack>
    #include<vector>
    #define tree int o,int l,int r
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define lo o<<1
    #define ro o<<1|1
    #define pb push_back
    #define mp make_pair
    #define ULL unsigned long long
    #define LL long long
    #define inf 0x7fffffff
    #define eps 1e-7
    #define N 2009
    #define M 2
    #define mod 1000000009
    using namespace std;
    int m,n,T,t,x,y,u;
    int ch[N][M],v[N],sz;
    int f[N],last[N],len;
    char str[29],a[209],b[209],*s;
    int d[N][809][2];
    char tr[10][5]={"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001"};
    void init()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(v,0,sizeof(v));
        memset(last,0,sizeof(last));
        memset(d,-1,sizeof(d));
    }
    int idx(char c)
    {
        return c-'0';
    }
    void insert(char str[],int val)
    {
        int u=0;
        for(int i=0; str[i]; i++)
        {
            int c=idx(str[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        v[u]=val;
    }
    void getac()
    {
        f[0]=0;
        queue<int>q;
        for(int c=0; c<M; c++)
        {
            int u=ch[0][c];
            if(u)
            {
                f[u]=0;
                q.push(u);
                last[u]=v[u];//////////////////
            }
        }
        while(!q.empty())
        {
            int r=q.front();
            q.pop();
            for(int c=0; c<M; c++)
            {
                int u=ch[r][c];
                if(!u)
                {
                    ch[r][c]=ch[f[r]][c];
                }
                else
                {
                    q.push(u);
                    int s=f[r];
                    f[u]=ch[s][c];
                    last[u]=(v[u]||last[f[u]]);/////////////////
                }
            }
        }
    }
    int ok(int u,int k)
    {
        for(int i=3;i>=0;i--)
        {
            u=ch[u][((k>>i)&1)];
            if(last[u])
            {
                u=-1;break;
            }
        }
        return u;
    }
    int dp(int u,int sub,int up,int zero)//sub表示还剩下的位数,0表示是否前导0
    {
        if(sub==0)return 1;
        if(d[u][sub][zero]!=-1&&(!up))
        return d[u][sub][zero];
        int ans=0;
        int end=(up?idx(s[n-sub]):9);
        int i=0;
        if(zero)//处理前导0
        {
            ans+=dp(u,sub-1,up&&(0==end),1);
            ans%=mod;
            i++;
        }
        for(;i<=end;i++)
        {
            int c=ok(u,i);
            if(c!=-1)
            {
                ans+=dp(c,sub-1,up&&(i==end),0);
                ans%=mod;
            }
        }
        if(!up)
        d[u][sub][zero]=ans;
        return ans;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
        scanf("%d",&T);
        while(T--)
        {
            init();
            scanf("%d",&n);
            for(int i=1; i<=n; ++i)
            {
                scanf("%s",str);
                insert(str,1);
            }
            getac();
            scanf("%s%s",a,b);
            n=strlen(a);
            for(int i=n-1;i>=0;i--)
            if(a[i]=='0')
                a[i]='9';
            else
            {
                a[i]--;break;//有前导0也没事
            }
            s=a;
            int ans=dp(0,n,1,1);//d[u][sub][zero]的sub是从n->0,不是从0->n(WA)
            s=b;
            n=strlen(b);
            int ans2=dp(0,n,1,1);
            ans=ans2-ans;
            if(ans<0)ans+=mod;
            ans%=mod;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    图书管理系统---基于form组件和modelform改造添加和编辑
    Keepalived和Heartbeat
    SCAN IP 解释
    Configure Active DataGuard and DG BROKER
    Oracle 11gR2
    我在管理工作中積累的九種最重要的領導力 (李開復)
    公募基金公司超融合基础架构与同城灾备建设实践
    Oracle 11g RAC for LINUX rhel 6.X silent install(静默安装)
    11gR2 静默安装RAC 集群和数据库软件
    Setting Up Oracle GoldenGate 12
  • 原文地址:https://www.cnblogs.com/sbaof/p/3377484.html
Copyright © 2011-2022 走看看