ZOJ Problem Set - 3494 BCD Code AC自动机+数位DP

来源:互联网 发布:淘宝服装外景拍摄 编辑:程序博客网 时间:2024/04/30 08:15

BCD Code

Time Limit: 5 Seconds      Memory Limit: 65536 KB

Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is represented by its own binary sequence.To encode a decimal number using the common BCD encoding, each decimal digit is stored in a 4-bit nibble:

Decimal:    0     1     2     3     4     5     6     7     8     9BCD:     0000  0001  0010  0011  0100  0101  0110  0111  1000  1001

Thus, the BCD encoding for the number 127 would be:

 0001 0010 0111

We are going to transfer all the integers from A to B, both inclusive, with BCD codes.But we find that some continuous bits, named forbidden code, may lead to errors. If the encoding of some integer contains these forbidden codes, the integer can not be transferred correctly.Now we need your help to calculate how many integers can be transferred correctly.

Input

There are multiple test cases. The first line of input is an integer T ≈ 100 indicating the number of test cases.

The first line of each test case contains one integer N, the number of forbidden codes ( 0 ≤N ≤ 100).Then N lines follow, each of which contains a 0-1 string whose length is no more than 20.The next line contains two positive integersA and B. Neither A or B contains leading zeros and 0 <AB < 10200.

Output

For each test case, output the number of integers between A and B whose codes do not contain any of theN forbidden codes in their BCD codes.For the result may be very large, you just need to output itmod 1000000009.

Sample Input

31001 101001 100111111 100

Sample Output

3998

  BCD码是每个数字用4位2进制表示,[A,B]区间内有多少个数的BCD码不包含给的串。

  很少写数位DP,也几乎没怎么写过记忆化搜索的形式(虽然一般都推荐这么写),嗯,这题挺好的。

  先用AC自动机处理出bcd[i][j],表示在节点i,下一个数字为j到达的节点。

  DP的时候,cur是当前位,s是当前节点,e为是否到达边缘,也决定了这一位能取多大,z是处理前导0,dp[cur][s]是在e为0并且z为0的情况。

  区间为[A,B],那么需要A-1,字符串处理A-1。

#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<iostream>#include<queue>using namespace std;typedef long long LL;const int MAXN=110;const int MAXM=25;const int MAXL=210;const int MAXNODE=MAXN*MAXM;const int LOGMAXN=50;const int INF=0x3f3f3f3f;const int SIGMA_SIZE=2;const int MOD=1000000009;int T,N;int bcd[MAXNODE][12];int num[MAXL];char str[MAXL];LL dp[MAXL][MAXNODE];struct AC{    int ch[MAXNODE][SIGMA_SIZE];    int val[MAXNODE];    int f[MAXNODE];    int sz;    void clear(){        memset(ch[0],0,sizeof(ch[0]));        val[0]=0;        sz=1;    }    int idx(char c){        return c-'0';    }    int insert(char* s,int v){        int u=0;        for(int i=0;s[i];i++){            int c=idx(s[i]);            if(!ch[u][c]){                memset(ch[sz],0,sizeof(ch[sz]));                val[sz]=0;                ch[u][c]=sz++;            }            u=ch[u][c];        }        val[u]=v;    }    void get_fail(){        queue<int> q;        f[0]=0;        for(int c=0;c<SIGMA_SIZE;c++){            int u=ch[0][c];            if(u){                f[u]=0;                q.push(u);            }        }        while(!q.empty()){            int r=q.front();            q.pop();            for(int c=0;c<SIGMA_SIZE;c++){                int u=ch[r][c];                if(!u){                    ch[r][c]=ch[f[r]][c];                    continue;                }                q.push(u);                f[u]=ch[f[r]][c];                val[u]|=val[f[u]];            }        }    }}ac;void get_bcd(){    memset(bcd,-1,sizeof(bcd));    for(int i=0;i<ac.sz;i++)        for(int j=0;j<10;j++){            int u=i,flag=1;            for(int k=3;k>=0;k--){                int c;                if(j&(1<<k)) c=1;                else c=0;                if(ac.val[ac.ch[u][c]]){                    flag=0;                    break;                }                u=ac.ch[u][c];            }            if(flag) bcd[i][j]=u;        }}LL dfs(int cur,int s,int e,int z){    if(cur<0) return 1;    if(!e&&dp[cur][s]!=-1) return dp[cur][s];    LL ans=0;    if(z) ans=(ans+dfs(cur-1,s,e&&num[cur]==0,1))%MOD;    else if(bcd[s][0]!=-1) ans=(ans+dfs(cur-1,bcd[s][0],e&&num[cur]==0,0))%MOD;    int end=e?num[cur]:9;    for(int i=1;i<=end;i++) if(bcd[s][i]!=-1){        ans=(ans+dfs(cur-1,bcd[s][i],e&&i==end,0))%MOD;    }    if(!e&&!z) dp[cur][s]=ans;    return ans;}int main(){    freopen("in.txt","r",stdin);    scanf("%d",&T);    while(T--){        scanf("%d",&N);        ac.clear();        for(int i=0;i<N;i++){            scanf("%s",str);            ac.insert(str,1);        }        ac.get_fail();        get_bcd();        memset(dp,-1,sizeof(dp));        scanf("%s",str);        int len=strlen(str);        for(int i=len-1;i>=0;i--){            if(str[i]>'0'){                str[i]--;                break;            }            else str[i]='9';        }        reverse(str,str+len);        for(int i=0;i<len;i++) num[i]=str[i]-'0';        LL ans=0;        ans-=dfs(len-1,0,1,1);        scanf("%s",str);        len=strlen(str);        reverse(str,str+len);        for(int i=0;i<len;i++) num[i]=str[i]-'0';        ans+=dfs(len-1,0,1,1);        ans=(ans+MOD)%MOD;        printf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击