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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

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

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3494 这题没什么好说的,就是数位DP,用AC自动机预处理一下就行...
  • willinglive
  • willinglive
  • 2014年12月23日 20:18
  • 369

ZOJ 3494 BCD Code (*AC自动机+数位DP 待整理)

Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is represented by ...
  • u014665013
  • u014665013
  • 2017年04月28日 11:58
  • 355

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

题意:从0到9都用4位的二进制数表示,叫做BCD码,给出n个模式串,是不能出现的串,给出整数A和整数B,A ...
  • u013392752
  • u013392752
  • 2015年10月11日 22:16
  • 138

AC自动机+DP小结 (一)

好久没有更新博客了,最近真是懒到家了,南京赛前重点复习了下AC自动机+DP方面的题,写下来总结一下。 HDU 2457  DNA repair http://acm.hdu.edu.cn/showpr...
  • dyx404514
  • dyx404514
  • 2013年11月13日 11:12
  • 3414

AC自动机总结

AC自动机总结 0.引言:       由于大连现场赛的一道 AC自动机+ DP的题目(zoj3545 Rescue the Rabbit)被小媛同学推荐看 AC自动机。经过一段时间的努力,终于把...
  • mobius_strip
  • mobius_strip
  • 2014年03月30日 02:18
  • 18825

(带讲解)bzoj1030 AC自动机+dp

第一道AC自动机上的dp题意是给出一些字符串,求长为m的字符串包含这些的一共有多少个,字符集A-Z首先运用补集转换,转而求不含这些串的个数,最后用26^M减掉就行根据输入的字符串建立AC自动机dp[i...
  • thchuan2001
  • thchuan2001
  • 2017年02月26日 20:47
  • 564

hdu4057(ac自动机,状态压缩dp)

Rescue the Rabbit Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe...
  • martinue
  • martinue
  • 2016年03月15日 14:42
  • 571

BZOJ1030 [JSOI2007]文本生成器(AC自动机+dp)

【题解】 与poj2778有类似之处,只不过本题模板串太长,无法用到矩阵,而文本较短,适于dp ans = 26^m - 不含任意单词的文本数  不含任意单词的文本数 的求法: 转...
  • cjk_cjk
  • cjk_cjk
  • 2015年06月24日 18:09
  • 732

ac自动机最详细的讲解,让你一次学会ac自动机。

在没学ac自动机之前,觉得ac自动机是个很神奇,很高深,很难的算法,学完之后发现,ac自动机确实很神奇,很高深,但是却并不难。 我说ac自动机很神奇,在于这个算法中失配指针的妙处(好比kmp算法中的...
  • creatorx
  • creatorx
  • 2017年05月02日 19:51
  • 14949

[置顶]AC自动机-算法详解

What's Aho-Corasick automaton?   一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一。   简单的说,KMP用来在一篇文章中匹配一...
  • u013371163
  • u013371163
  • 2017年03月05日 17:35
  • 1137
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ZOJ - 3494 BCD Code(AC自动机+数位DP)
举报原因:
原因补充:

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