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

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;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010660276/article/details/46801505
个人分类: 数位dp AC自动机
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

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

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭