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. Parallels Desktop 12 for Mac 破解版

    Parallels Desktop for Mac 是功能最强大灵活度最高的虚拟化方案,无需重启即可在同一台电脑上随时访问Windows和Mac两个系统上的众多应用程序.从仅限于PC的游戏到生产力软件 ...

  2. webpack 3.X学习之多页面打包

    简介 我们开发不可能只写一个页面,每次都要写很多页面,这时为了开发效率,我们使用前端自动化工具webpack,那么webpack是如何打包页面的呢?又是如何打包多页面的呢? 单页面打包 我们知道要打包 ...

  3. Scala 安装 Exception in thread "main" java.lang.VerifyError: Uninitialized object exists on backward branch 96

    windows下载安装完最新版本的Scala(2.12.4)后,终端如下错误 C:\Users\Administrator>scala -versionException in thread & ...

  4. 基于Java Mail 进行发送(带附件和压缩附件)的邮件

    刚进公司的training, 下面是要求: Self-study of Java Mail library:  http://www.oracle.com/technetwork/java/javam ...

  5. 安装spark单机环境

    (假定已经装好的hadoop,不管你装没装好,反正我是装好了) 1 下载spark安装包 http://spark.apache.org/downloads.html 下载spark-1.6.1-bi ...

  6. 例子:韩顺平JavaScript----JS乌龟抓小鸡游戏

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. libcurl的使用

    http://blog.csdn.net/ixiaochouyu/article/details/47998267

  8. ADO.NET访问数据库

    1:ADO.NET数据库的方法和技术 2:ADO.NET的主要组成: 1>DataSet(数据集)-----独立于数据间的数据访问 2>.NETFramework(数据提供程序)----- ...

  9. 高效的CSS代码(2)

    ——阅读笔记,欢迎纠错^_^ 内容比较零散..... 1.让浮动元素的父容器根据元素的高度而自适应高度的方法: <div class="clearfix"><di ...

  10. 通过pyenv和virtualenv创建多版本Python虚拟环境

    虚拟环境使用第三方工具virtualenv创建,首先输入以下命令检查系统是否已经安装virtualenv. $ virtualenv --version 如果显示virtualenv版本号,则说明已经 ...