AC自动机+数位DP。

  大致题意:

    BCD码就是把一个数十进制下的每一位分别用4位的二进制表示。

    给你一坨01串,问你在一个区间内,有多少个数的BCD码不包含任何一个字符串。

  因为涉及到多个串的匹配问题...所以要在AC自动机上DP

  f[i][j]表示在自动机上的节点i,再往后走j步 的合法方案数。(合法就是说,经过的路径上不包含任何一个给定字符串)

  建完AC自动机后,把非法的节点都删掉,再求出CH[i][j]表示从i节点出发,经过数字j后到达的节点(0<=j<=9),这样好转移= =。

  一开始想写递归版本的。。前导0什么的完全无力TAT

  后来干脆用记忆化搜索求f数组,然后统计答案的时候用正常姿势。。这样好写多了>_<

  结果交完直接#1了。。我是没看出来自己的写法哪里常数优越= =

  其实这题只比普通模版题多了个AC自动机而已。。。其他甚至还简单点

  就算是递归版的,只要好好想一下前导零的问题就行了吧...网上递归版的标程也不长

 #include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int modd=;
int fail[],ch[][];
int CH[][];
int f[][],u[][];//f[i][j]在自动机上的i节点时,再往后走j步的合法方案数
int i,j,k,n,m,tot,T,ans,len;
bool gg[]; char s[];int dl[]; inline void insert(int len){
int i,now=;
for(i=;i<len;i++)
s[i]-='',now=ch[now][s[i]]?ch[now][s[i]]:(ch[now][s[i]]=++tot);
gg[now]=;
}
inline void build(){
int l=,r=,i,now,tmp;
while(l<r){
now=dl[++l];
for(i=;i<=;i++)if(ch[now][i]){
for(tmp=fail[now];tmp&&!ch[tmp][i];tmp=fail[tmp]);
fail[ch[now][i]]=(now==)?:ch[tmp][i]; gg[ch[now][i]]|=gg[fail[ch[now][i]]]|gg[now];
dl[++r]=ch[now][i];
}else{
for(tmp=fail[now];tmp&&!ch[tmp][i];tmp=fail[tmp]);
ch[now][i]=ch[tmp][i];
}
}
for(i=;i<=tot;i++)for(j=;j<=;j++)if(gg[ch[i][j]]||gg[i])ch[i][j]=-;
for(i=;i<=tot;i++)if(!gg[i])
for(j=;j<=;j++){
for(now=i,k=;k&&now!=-;k>>=)
now=ch[now][(k&j)!=];
CH[i][j]=now;//printf(" %d->%d %d\n",i,j,CH[i][j]);
}
for(i=;i<=tot;i++)if(!gg[i])f[i][]=,u[i][]=T;
}
inline int dfs(int x,int step){
if(u[x][step]==T)return f[x][step];
int ans=;
for(int i=;i<=;i++)if(CH[x][i]!=-)
ans+=dfs(CH[x][i],step-),ans-=ans>=modd?modd:;
u[x][step]=T,f[x][step]=ans;//printf(" f: %d %d %d\n",x,step,f[x][step]);
return ans;
}
inline int get(int len){//求区间[1,len)内合法方案数
register int i,j,ans=,now;
for(i=;i<len;i++)s[i]-=;
for(i=;i<len;i++)for(j=;j<=;j++)if(CH[][j]!=-)
ans+=dfs(CH[][j],i-),ans-=ans>=modd?modd:;
for(i=;i<s[];i++)if(CH[][i]!=-)ans+=dfs(CH[][i],len-),ans-=ans>=modd?modd:; now=CH[][s[]];
for(i=;i<len&&now!=-;i++){
for(j=;j<s[i];j++)if(CH[now][j]!=-)ans+=dfs(CH[now][j],len-i-),ans-=ans>=modd?modd:;
now=CH[now][s[i]];
}
return ans;
}
inline void add(){
int i,j;
for(i=len-;i>=;i--)if(s[i]!='')break;
if(i>=)
for(s[i]++,j=i+;j<len;j++)s[j]='';
else{
for(s[]='',i=;i<=len;i++)s[i]='';
len++;
}
}
int main(){
for(scanf("%d",&T);T;T--){
scanf("%d",&n);memset(gg,,tot+);memset(ch,,(tot+)<<);tot=;
for(i=;i<=n;i++)
scanf("%s",s),insert(strlen(s));
build();
scanf("%s",s);len=strlen(s);ans=-get(len);
scanf("%s",s);len=strlen(s);add();ans+=get(len);
if(ans<)ans+=modd;
printf("%d\n",ans);
}
return ;
}

[ZOJ3494]BCD Code的更多相关文章

  1. zoj3494 BCD Code(AC自动机+数位dp)

    Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is represented by ...

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

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

  3. ZOJ 3494 BCD Code (AC自己主动机 + 数位DP)

    题目链接:BCD Code 解析:n个病毒串.问给定区间上有多少个转换成BCD码后不包括病毒串的数. 很奇妙的题目. . 经典的 AC自己主动机 + 数位DP 的题目. 首先使用AC自己主动机,得到b ...

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

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

  5. zoj 3494:BCD Code

    Description Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is rep ...

  6. ZOJ 3494 BCD Code (数位DP,AC自动机)

    题意: 将一个整数表示成4个bit的bcd码就成了一个01串,如果该串中出现了部分病毒串,则是危险的.给出n个病毒串(n<=100,长度<21),问区间[L,R]中有几个数字是不含病毒串的 ...

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

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

  8. FZU 2113 BCD Code 数位dp

    数位dp,但是很奇怪的是我在虚拟oj上用GUC C++提交会wa,用Visual c++提交正确,但是加上注释后提交又莫名CE--好任性啊 0 ,0 题目思路:看代码吧 注释很详细 #include& ...

  9. [转]数位dp小记

    转载自:http://blog.csdn.net/guognib/article/details/25472879 参考: http://www.cnblogs.com/jffifa/archive/ ...

随机推荐

  1. 一些常用的vim编辑器快捷键:

    一些常用的vim编辑器快捷键: h」.「j」.「k」.「l」,分别控制光标左.下.上.右移一格. 按「ctrl」+「b」:屏幕往“后”移动一页. 按「ctrl」+「f」:屏幕往“前”移动一页. 按「c ...

  2. android v4兼容包

    一句话解释android兼容包就是:支持更多的组件,样式更好看了.好粗糙的解释啊! 我们都知道Android一些SDK比较分裂,为此google官方提供了Android Support Library ...

  3. TXDragon的大火题合集

    还有三个题没写,弃疗了 Solution

  4. yum 命令详解

    一. yum          作用:                     yum 命令是在Fedora 和RedHat 以及SUSE 中基于rpm 的软件包管理器,它可以使系统管理人员交互和自动 ...

  5. 关于理解python类的小题

    今天看了python部落翻译的一篇<一道python类的小题>文章,感觉挺有启发性,记录下来: print('A') class Person(object): print('B') de ...

  6. [编织消息框架][JAVA核心技术]动态代理应用7-IRpcSend实现

    根据设计生成两个接口,IRpcSend send方法返回数据要求包装成QResult对象 public interface IRpcSend { public <T> QResult< ...

  7. VS2017 调试不能命中断点问题

    去掉勾

  8. DevOps/TestOps概念

    天下大势分久必合合久必分,早期的软件开发只有软件工程师一人完成,为了提高效率逐渐实行分工模式:开发.测试.运维.不同角色担任不同的任务.分工越来越细之后带来了问题也越来越突出,那就是各角色之间的沟通成 ...

  9. [C#]如何访问及调用类中私有成员及方法

    本文为原创文章.源代码为原创代码,如转载/复制,请在网页/代码处明显位置标明原文名称.作者及网址,谢谢! 开发工具:VS2017 语言:C# DotNet版本:.Net FrameWork 4.0及以 ...

  10. MicroPython教程之TPYBoard v102 CAN总线通信

    0x00前言 CAN是控制器局域网络(ControllerAreaNetwork,CAN)的简称,是ISO国际标准化的串行通信协议.CAN总线结构简单,只需2根线与外部相连,并且内部集成了错误探测和管 ...