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 ( 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 integers A and B. Neither A or B contains leading zeros and 0 < A ≤ B < 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

题意:给出一些模式串,给出一个范围[A,B],求出区间内有多少个数,写成BCD之后,不包含模式串。

思路:先用AC自动机存下不符合的节点,然后预处理出bcd[i][j]表示ac自动机节点i走j这个数后的节点编号或者-1,然后用dp[i][j]表示前i位,当前ac节点为j的方案数。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 300050
#define maxnode 2050
#define MOD 1000000009
int bcd[maxnode][11]; //bcd[i][j]表示ac自动机状态i走j步后的状态 struct trie{
int sz,root,val[maxnode],next[maxnode][2],fail[maxnode];
int q[11111];
void init(){
int i;
sz=root=0;
val[0]=0;
for(i=0;i<2;i++){
next[root][i]=-1;
}
}
void charu(char *s){
int i,j,u=0;
int len=strlen(s);
for(i=0;i<len;i++){
int c=s[i]-'0';
if(next[u][c]==-1){
sz++;
val[sz]=0;
next[u][c]=sz;
u=next[u][c];
for(j=0;j<2;j++){
next[u][j]=-1;
}
}
else{
u=next[u][c];
}
}
val[u]=1;
} void build(){
int i,j;
int front,rear;
front=1;rear=0;
for(i=0;i<2;i++){
if(next[root][i]==-1 ){
next[root][i]=root;
}
else{
fail[next[root][i] ]=root;
rear++;
q[rear]=next[root][i];
}
}
while(front<=rear){
int x=q[front];
if(val[fail[x]]) //!!!!!
val[x]=1;
front++;
for(i=0;i<2;i++){
if(next[x][i]==-1){
next[x][i]=next[fail[x] ][i];
}
else{
fail[next[x][i] ]=next[fail[x] ][i];
rear++;
q[rear]=next[x][i];
} }
}
}
}ac; int change(int jiedian,int num)
{
int i,j,len=0;
int shu[10];
while(num){
shu[++len]=num%2;
num/=2;
}
while(len<4)shu[++len]=0;
for(i=4;i>=1;i--){
if(ac.val[ac.next[jiedian][shu[i] ] ]==1 )return -1;
else jiedian=ac.next[jiedian][shu[i] ];
}
return jiedian;
} void pre_init()
{
int i,j;
for(i=0;i<=ac.sz;i++){
for(j=0;j<=9;j++){
bcd[i][j]=change(i,j);
}
}
} int wei[300];
ll dp[300][maxnode]; ll dfs(int pos,int jiedian,int lim,int zero)
{
int i,j;
if(pos==-1)return 1;
if(lim==0 && zero==0 && dp[pos][jiedian]!=-1){ //这里和下面同理,也不要省略zero==0
return dp[pos][jiedian];
}
int ed=lim?wei[pos]:9;
ll ans=0;
for(i=0;i<=ed;i++){
if(i==0){
if(zero){
ans+=dfs(pos-1,jiedian,0,1);
ans%=MOD;
}
else{
if(bcd[jiedian][0]!=-1){
ans+=dfs(pos-1,bcd[jiedian][0],lim&&i==ed,0);
ans%=MOD;
}
}
continue;
}
if(bcd[jiedian][i]!=-1){
ans+=dfs(pos-1,bcd[jiedian][i],lim&&i==ed,0);
ans%=MOD;
}
}
if(lim==0 && zero==0 ){ //这里要注意,不能写成if(lim==0)dp[pos][jiedian]=ans;因为zero不为0的话,即最高位还没有确定,那么可能后面几位都可以跳过去,
dp[pos][jiedian]=ans; //即可以把0跳过,但是对于最高位确定的情况下,后面不管加什么数都不能跳过去,即使是0也要在ac自动机上走0这个数.
}
return ans;
} ll cal(char *s)
{
int i,j,len;
len=strlen(s);
for(i=0;i<len;i++){
wei[i]=s[len-1-i]-'0';
}
return dfs(len-1,0,1,1);
} char s1[300],s2[300],s[30];
int main()
{
int n,m,i,j,T,len1,len2;
scanf("%d",&T);
while(T--)
{
ac.init();
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%s",s);
ac.charu(s);
}
ac.build();
pre_init();
scanf("%s",s1);
len1=strlen(s1);
reverse(s1,s1+len1);
for(i=0;i<len1;i++){ //这里算的是(l,r],所以先要把s1的数减去1
if(s1[i]-'0'>0){
s1[i]--;break;
}
else{
s1[i]='9';
}
}
memset(dp,-1,sizeof(dp));
ll ans=0;
if(s1[len1-1]=='0')len1-=1;
s1[len1]='\0';
reverse(s1,s1+len1);
ans-=cal(s1);
ans%=MOD;
scanf("%s",s2);
ans+=cal(s2);
ans%=MOD;
if(ans<0){
ans=(ans+MOD)%MOD;
}
printf("%lld\n",ans);
}
return 0;
}

zoj3494 BCD Code(AC自动机+数位dp)的更多相关文章

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

    BCD Code Time Limit: 5 Seconds      Memory Limit: 65536 KB Binary-coded decimal (BCD) is an encoding ...

  2. zoj3494BCD Code(ac自动机+数位dp)

    l链接 这题想了好一会呢..刚开始想错了,以为用自动机预处理出k长度可以包含的合法的数的个数,然后再数位dp一下就行了,写到一半发现不对,还要处理当前走的时候是不是为合法的,这一点无法移到trie树上 ...

  3. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  4. 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp

    题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...

  5. BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)

    题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...

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

    题意: 问A到B之间的所有整数,转换成BCD Code后, 有多少个不包含属于给定病毒串集合的子串,A,B <=10^200,病毒串总长度<= 2000. BCD码这个在数字电路课上讲了, ...

  7. ZOJ 3494 BCD Code(AC自动机 + 数位DP)题解

    题意:每位十进制数都能转化为4位二进制数,比如9是1001,127是 000100100111,现在问你,在L到R(R <= $10^{200}$)范围内,有多少数字的二进制表达式不包含模式串. ...

  8. BZOJ3530:[SDOI2014]数数(AC自动机,数位DP)

    Description 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3 ...

  9. 【JZOJ3624】【SDOI2014】数数(count) AC自动机+数位dp

    题面 100 容易想到使用AC自动机来处理禁忌子串的问题: 然后在自动机上数位dp,具体是: \(f_{i,j,0/1}\)表示填了\(i\)位,当前在自动机的第\(j\)个结点上,\(0\)表示当前 ...

随机推荐

  1. COW技术重置虚拟机

    最近使用COW技术做虚拟机重置,结果成功了,特地来给大家分享一下这次的成果! 文章目录 一.COW技术是什么? 二.重置虚拟机步骤 总结 往期杂文 一.COW技术是什么? Copy On Write, ...

  2. 剑指offer 面试题6:从尾到头打印链表

    题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 编程思想 从前往后遍历,将值存入栈中,然后打印栈中内容即可. 编程实现 /** * struct ListNode { * ...

  3. Centos 7 下的KVM虚拟机

    一 什么是KVM虚拟机: KVM虚拟机 Kernel-based Virtual Machine的简称,是一个开源的系统虚拟化模块,自Linux 2.6.20之后集成在Linux的各个主要发行版本中. ...

  4. windows下使用mingw和msvc静态编译Qt5.15.xx

    windows下使用mingw和msvc静态编译Qt5.15.xx 下载并安装相关依赖软件 Python version 2.7 https://www.python.org/downloads/ ( ...

  5. OpenID协议

    背景 当我们要使用一个网站的功能时,一般都需要注册想用的账号.现在的互联网应用很多,一段时间之后你会发现你注册了一堆账号密码,根本记不住. 你可能会想到所有的网站都用同一套用户名和密码,这样虽然能解决 ...

  6. 数据分析 Pandas 简介和它的的数据结构

    本文主要讲Pandas 的Series和DataFrame 的相关属性和操作 1.Series的相关属性和操作# --Series是一种类似于一维数组的对象,只能存放一维数组!由以下两部分组成:# v ...

  7. 到底什么是哈希Hash?

    有次面试被问到这个问题? 我说是经过运算的一串字符串,这个回答显然是让人不满意,连自己都不满意! 但是又对其很模糊,那么到底什么是Hash呢? 定义 Hash一般翻译为散列,还有音译为哈希,本文我们统 ...

  8. 阿里云 RTC QoS 屏幕共享弱网优化之若干编码器相关优化

    屏幕共享是视频会议中使用频率最高的功能之一,但在实际场景中用户所处网络环境复杂,常遇到丢包或者拥塞的情况,所以如何优化弱网环境下的用户体验也成为了音视频通信中重要的一环.本文主要分享阿里云 RTC Q ...

  9. JMS监听Oracle AQ

    该文档中,oracle版本为11g,jdk版本1.8,java项目为maven构建的springboot项目,springboot的版本为2.1.6,并使用了定时任务来做AQ监听的重连功能,解决由于外 ...

  10. 【译】Async/Await(三)——Aysnc/Await模式

    原文标题:Async/Await 原文链接:https://os.phil-opp.com/async-await/#multitasking 公众号: Rust 碎碎念 翻译 by: Praying ...