【第21期】观点:人工智能到底用 GPU?还是用 FPGA?

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)

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

poj 1625 Censored! 【AC自动机 + DP + 强力大数模版】

1y,还是这个大数模版给力,自己敲了个动态的大数模版结果连加法都算不对。。。 #include&lt;iostream&gt; #include&lt;vector&gt; #include&lt;cstdio&gt; #include&lt;map&gt; #include&lt;cstring&gt; #include&lt;queue&gt; using namespace std; #ifdef _WIN32 #

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

题目链接:zoj 3494 BCD Code 题目大意:给定n个2进制串,然后有一个区间l,r,问说l,r之间有多少个数转换成BCD二进制后不包含上面的2进制串。 解题思路:AC自动机+数位dp。...

[AC自动机]zoj 3228:Searching the String

大致题意:     给出n组模式串数据,每组数据由一个01数字和一个模式串组成,再给出一个文本串。对于每组模式串数据,分别统计其在文本串中出现了多少次,如果前面的数字是0,则代表计数的时候可以重叠,如果是0则代表不能重叠。   大致思路:    好麻烦的一道题,有思路但是真的很难敲,要用多个数组来控制好数据之间的关系,最后还狂mle……擦。对于可以重叠的,直接ac自动机即可,对于不能重叠的,求出当前的位置距离其上次匹配的距离再判断即可。   <pre name="code" class=

Zoj 3494 BCD Code (字符串_AC自动机(数位DP))

题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4317 题目大意: 问A到B之间的所有整数,转换成...

zoj 3494 BCD Code

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4317 题目大意:求a到b之间的数满足翻译成bcd码后没有禁止串的个数。 题目思路:ac自动机加按位dp,需要注意的是,一般在a的长度比b短时,我们会进行加零处理,这样由于0是不存在的,匹配的时候前导0也不能进行匹配,需要特殊判断一下。 <pre class="cp

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

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

[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...

Aho-Corasick 多模式匹配算法、AC自动机详解

有时候可能需要按一个关键字词列表来过滤信息,例如过滤黄色或其他非法信息   调用indexOf方法来查找关键字集合看起来效率不高,Aho-C
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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