ZOJ - 3494 BCD Code(AC自动机+数位DP)

原创 2015年07月08日 11:47:59

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 9
BCD: 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 (0N100). 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 integers A 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 the N forbidden codes in their BCD codes. For the result may be very large, you just need to output it mod 1000000009.

Sample Input

3
1
00
1 10
1
00
1 100
1
1111
1 100

Sample Output

3
9
98

思路:现在AC自动机真的都忘干净了。。。
多模式串匹配,自然想到AC自动机,首先对输入的串建立AC自动机,然后求出BCD[i][j]数组,表示在节点i后面加上数字j(10进制)转移到的节点编号,然后dfs数位dp,除了一般要加的限制,还要考虑不能包含单词节点

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=2010;
const int MOD=1e9+9;
const int SIGMA_SIZE=2;
int N;
char str[210];
int A,B;
int BCD[maxn][10];
int dig[maxn];
LL dp[210][maxn];
struct AC
{
    int ch[maxn][2],val[maxn];
    int fail[maxn];
    int sz;
    void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}
    int idx(char x){return x-'0';}
    void insert(char *s)
    {
        int n=strlen(s);
        int u=0;
        for(int i=0;i<n;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]=1;
    }
    void getfail()
    {
        queue<int> q;
        int u=0;
        fail[0]=0;
        for(int c=0;c<SIGMA_SIZE;c++)
        {
            u=ch[0][c];
            if(u){fail[u]=0;q.push(u);}
        }
        while(!q.empty())
        {
            int r=q.front();q.pop();
            if(val[fail[r]])val[r]=1;
            for(int c=0;c<SIGMA_SIZE;c++)
            {
                u=ch[r][c];
                if(!u){ch[r][c]=ch[fail[r]][c];continue;}
                q.push(u);
                int v=fail[r];
                while(v&&!ch[v][c])v=fail[v];
                fail[u]=ch[v][c];
            }
        }
    }
    int add(int pos,int x)
    {
        if(val[pos])return -1;
        for(int i=3;i>=0;i--)
        {
            if(val[ch[pos][(x>>i)&1]])return -1;
            pos=ch[pos][(x>>i)&1];
        }
        return pos;
    }
    void init()
    {
        for(int i=0;i<sz;i++)
        {
            for(int j=0;j<10;j++)
            {
                BCD[i][j]=add(i,j);
            }
        }
    }
    LL dfs(int cur,int e,int z,int s)
    {
        if(cur<0)return 1;
        if(!e&&!z&&dp[cur][s]!=-1)return dp[cur][s];
        LL ans=0;
        int end=(e?dig[cur]:9);
        for(int i=0;i<=end;i++)
        {
            if(z&&!i)
                (ans+=dfs(cur-1,e&&i==end,1,s))%=MOD;
            else
            {
                if(BCD[s][i]!=-1)
                    (ans+=dfs(cur-1,e&&i==end,0,BCD[s][i]))%=MOD;
            }

        }
        if(!e&&!z)dp[cur][s]=ans;
        return ans;
    }
    LL cal(char *s)
    {
        int len=strlen(s);
        for(int i=0;i<len;i++)
            dig[i]=s[len-i-1]-'0';
        return dfs(len-1,1,1,0);
    }
    void solve()
    {
        init();
        scanf("%s",str);
        memset(dp,-1,sizeof(dp));
        int len=strlen(str);
        for(int i=len-1;i>=0;i--)
        {
            if(str[i]>'0')
            {
                str[i]--;
                break;
            }
            else str[i]='9';
        }
        LL ans=0;
        ans-=cal(str);
        scanf("%s",str);
        ans+=cal(str);
        ans=(ans+MOD)%MOD;
        printf("%lld\n",ans);
    }
}ac;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        ac.clear();
        for(int i=0;i<N;i++)
        {
            scanf("%s",str);
            ac.insert(str);
        }
        ac.getfail();
        ac.solve();
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

ZOJ 3494 BCD Code(AC自动机+数位DP)

题意:给出一些禁止串,问从A~B的数字用BCD码表示,并且不包含禁止串的数有多少。 思路:首先用禁止串建立AC自动机,然后数位DP……dp[i][j]表示在位置i,状态为j时的合法数字个数。另外,如...

zoj 3494 BCD Code (ac自动机+数位dp)

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4317 题意:给定N个01串,再给定区间[a,b],问区间[a,b]里面...

ZOJ 3494 BCD Code(AC自动机+数位DP)

ZOJ 3494 BCD Code(AC自动机+数位DP) http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3494 题意:给...

zoj 3494 BCD Code AC自动机+数位dp

一道很强大的数位dp+ac自动机题。题目要求a~bjian

ZOJ 3494 BCD Code(AC自动机+数位DP)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove  题目:给出一些模式串,给...

[AC自动机+数位DP] ZOJ3494 BCD Code

ZOJ3494 题意:先理解BCD编码,不是普通的二进制,设一个n位的整数x= An*10^n-1 + An-1*10^n-2 +...+ A1*10^0,那么x的BCD编码为An的二进制拼接上An...

zoj 3494 BCD Code AC自动机 + 数位dp

/************ AC自动机 + 数位dp 好题! 给出一些模式串,求区间内不出现这些串的数字串的个数 以这些模式串构建AC自动机, 建自动机的时候要注意记录好结束状态 预处理出所有状态...

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

题目大意: 就是现在有0~9对应的BCD码(就是对应的4位的二进制), 然后给出了n串(0 大致思路: 首先考虑到A和B的范围,暴力是不可行的,这里需要用到数位DP,也就是逐位确定的思...

【ZOJ】3494 BCD Code AC自动机+数位DP

传送门:【ZOJ】3494 BCD Code 题目分析:

【AC自动机】 ZOJ 3494 BCD Code

先对所有的串建立AC自动机,然后做数位DP,DP转移的时候就是AC自动机上的转移就行了。。 #include #include #include #include #include #in...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)