zoj3494 BCD Code(AC自动机+数位dp)
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)的更多相关文章
- ZOJ 3494 BCD Code(AC自动机+数位DP)
BCD Code Time Limit: 5 Seconds Memory Limit: 65536 KB Binary-coded decimal (BCD) is an encoding ...
- zoj3494BCD Code(ac自动机+数位dp)
l链接 这题想了好一会呢..刚开始想错了,以为用自动机预处理出k长度可以包含的合法的数的个数,然后再数位dp一下就行了,写到一半发现不对,还要处理当前走的时候是不是为合法的,这一点无法移到trie树上 ...
- 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 682 Solved: 364 Description 我们称一 ...
- 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp
题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...
- BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)
题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...
- BCD Code ZOJ - 3494 AC自动机+数位DP
题意: 问A到B之间的所有整数,转换成BCD Code后, 有多少个不包含属于给定病毒串集合的子串,A,B <=10^200,病毒串总长度<= 2000. BCD码这个在数字电路课上讲了, ...
- ZOJ 3494 BCD Code(AC自动机 + 数位DP)题解
题意:每位十进制数都能转化为4位二进制数,比如9是1001,127是 000100100111,现在问你,在L到R(R <= $10^{200}$)范围内,有多少数字的二进制表达式不包含模式串. ...
- BZOJ3530:[SDOI2014]数数(AC自动机,数位DP)
Description 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3 ...
- 【JZOJ3624】【SDOI2014】数数(count) AC自动机+数位dp
题面 100 容易想到使用AC自动机来处理禁忌子串的问题: 然后在自动机上数位dp,具体是: \(f_{i,j,0/1}\)表示填了\(i\)位,当前在自动机的第\(j\)个结点上,\(0\)表示当前 ...
随机推荐
- 图像质量评估论文 | Deep-IQA | IEEETIP2018
主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, gr ...
- SonarQube学习(六)- SonarQube之扫描报告解析
登录http://192.16.1.105:9000,加载项目扫描情况 点击项目名称,查看报告总览 开发人员主要关注为[问题]标签页. 类型 主要关注为bug和漏洞. 其中bug是必须要修复的,漏洞是 ...
- 【Docker】Docker启动停止重启 Redirecting to /bin/systemctl start docker.service
[root@liuawen local]# docker -v Docker version 1.13.1, build cccb291/1.13.1 [root@liuawen local]# 启动 ...
- kubernets之服务重定向
一 服务的强大功能之处的其他表现 前面介绍的所有有关服务的说明,都是将集群内部的pod应用暴露出来提供外部客户端或者内部的客户端进行访问,但是服务的强大之处远远不止于此 服务甚至可以将集群外部的应用 ...
- Upload - Labs (上)
Pass - 01: 1.尝试上传一个php文件:aaa.php,发现只允许上传某些图片类型,用bp抓包,发现http请求都没通过burp就弹出了不允许上传的提示框,这表明验证点在前端,而不在服务端 ...
- ctfhub技能树—RCE—综合过滤练习
打开靶机 查看页面信息 查看源码可以发现这一次过滤了很多东西,查看当前目录信息 查询到%0a为换行符,可以利用这个url编码进行命令注入,开始尝试 http://challenge-2a4584dab ...
- 错误捕捉过滤器 .NetCore版
前言 继承ExceptionFilterAttribute后,重写OnException函数. 统一捕捉所有报错,格式化返回前端. 代码实现 基类控制器 在基类控制器上添加[ErrorCatch]特性 ...
- JVM学习-运行时数据区域
目录 前言 运行时数据区 程序计数器 Java虚拟机栈 局部变量表 基础数据类型 对象引用 returnAddress 操作数栈 动态链接 方法返回地址 Java堆 方法区 类型信息 字段描述符 方法 ...
- 网络编程 — Windows TCP服务端和客户端
1. 服务端 #include <iostream> #include <signal.h> #include <forward_list> #include &l ...
- python(paramiko模块的简单使用)
#通过paramiko模块连接主机运行bash命令 import paramiko hostname = '192.168.88.31' port = 22 username = 'root' pas ...